From e72d2b8c344ad9ce4352fa684ce499ff8d4f5a4d Mon Sep 17 00:00:00 2001 From: Kyle Brown Date: Wed, 21 Oct 2020 12:19:42 -0700 Subject: [PATCH] feat(extensions): most of the extensions implementation, by kdb424 --- Makefile | 16 +- README.md | 61 +-- {kmk/boards => boards}/__init__.py | 0 boards/boardsource/3x4/README.md | 13 + .../boardsource/3x4/kb.py | 6 +- boards/boardsource/3x4/main.py | 30 ++ boards/boardsource/4x12/README.md | 21 + boards/boardsource/4x12/kb.py | 25 ++ boards/boardsource/4x12/main.py | 43 ++ boards/boardsource/5x12/README.md | 21 + boards/boardsource/5x12/kb.py | 25 ++ boards/boardsource/5x12/main.py | 46 +++ boards/boardsource/microdox/README.md | 19 + boards/boardsource/microdox/kb.py | 24 ++ boards/boardsource/microdox/main.py | 54 +++ boards/crkbd/README.md | 27 ++ .../nice_nano/crkbd.py => boards/crkbd/kb.py | 9 +- boards/crkbd/main.py | 67 +++ boards/ergo_travel/README.md | 21 + boards/ergo_travel/kb.py | 33 ++ boards/ergo_travel/main.py | 58 +++ .../fourtypercentclub}/__init__.py | 0 boards/fourtypercentclub/gherkin/README.md | 17 + boards/fourtypercentclub/gherkin/kb.py | 21 + boards/fourtypercentclub/gherkin/main.py | 67 +++ boards/fourtypercentclub/luddite/README.md | 18 + .../fourtypercentclub/luddite/converter_kb.py | 0 boards/fourtypercentclub/luddite/kb.py | 33 ++ .../fourtypercentclub/luddite/main.py | 11 +- boards/keebio/iris/README.md | 15 + boards/keebio/iris/kb.py | 43 ++ .../keebio/iris/kb_converter.py | 6 +- boards/keebio/iris/main.py | 95 +++++ boards/keebio/levinson/README.md | 15 + boards/keebio/levinson/kb.py | 23 ++ .../keebio/levinson/kb_converter.py | 6 +- boards/keebio/levinson/main.py | 132 ++++++ boards/keebio/nyquist/README.md | 16 + boards/keebio/nyquist/kb.py | 23 ++ .../keebio/nyquist/kb_converter.py | 6 +- .../keebio/nyquist/main.py | 16 +- {kmk/boards => boards}/klarank.py | 4 + boards/lily58/README.md | 20 + boards/lily58/kb.py | 32 ++ boards/lily58/main.py | 66 +++ boards/reviung39/README.md | 20 + boards/reviung39/kb.py | 27 ++ boards/reviung39/main.py | 48 +++ boards/reviung41/README.md | 20 + boards/reviung41/kb.py | 38 ++ boards/reviung41/main.py | 64 +++ boards/rhymestone/README.md | 19 + boards/rhymestone/kb.py | 15 + boards/rhymestone/main.py | 51 +++ boards/tg4x/README.md | 17 + boards/tg4x/kb.py | 31 ++ boards/tg4x/main.py | 36 ++ boot.py | 2 +- docs/Getting_Started.md | 71 ++++ docs/Offiially_Supported_Microcontrollers.md | 47 +++ docs/ble_hid.md | 31 ++ docs/config_and_keymap.md | 35 +- docs/debugging.md | 2 +- docs/examples.md | 16 - docs/extensions.md | 14 + docs/flashing.md | 2 +- docs/handwiring.md | 6 + docs/hardware.md | 35 -- docs/international.md | 35 ++ docs/keycodes.md | 71 +--- docs/layers.md | 21 + docs/leader.md | 68 ---- docs/led.md | 87 ++-- docs/media_keys.md | 23 ++ docs/modtap.md | 22 +- docs/modules.md | 15 + docs/porting_to_kmk.md | 71 ++++ docs/power.md | 42 ++ docs/rgb.md | 95 ++--- docs/sequences.md | 29 -- docs/split_keyboards.md | 70 +++- docs/support.md | 12 +- docs/tapdance.md | 8 +- kmk/ble.py | 102 ----- .../converter/fourtypercentclub/__init__.py | 0 kmk/boards/converter/keebio/__init__.py | 0 kmk/boards/converter/keebio/bdn9.py | 20 - kmk/boards/converter/keebio/fourier.py | 15 - kmk/boards/converter/keebio/iris_r1.py | 15 - kmk/boards/converter/keebio/lapace.py | 28 -- kmk/boards/converter/keebio/levinson_r1.py | 15 - kmk/boards/converter/keebio/nyquist_r1.py | 15 - kmk/boards/converter/keebio/quefrency.py | 25 -- kmk/boards/converter/keebio/rorschach.py | 15 - kmk/boards/converter/keebio/tragicforce68.py | 29 -- kmk/boards/converter/keebio/viterbi_r1.py | 15 - kmk/boards/converter/keebio/viterbi_r2.py | 15 - kmk/boards/converter/lets-split/__init__.py | 0 .../converter/lets-split/lets-split_r1.py | 15 - .../converter/lets-split/lets-split_r2.py | 15 - kmk/consts.py | 10 +- kmk/extensions/__init__.py | 29 +- kmk/extensions/international.py | 59 +++ kmk/extensions/leader.py | 111 ----- kmk/{ => extensions}/led.py | 76 ++-- kmk/extensions/media_keys.py | 55 +++ kmk/{ => extensions}/rgb.py | 294 ++++++++++---- kmk/extensions/split.py | 103 ----- kmk/handlers/layers.py | 124 ------ kmk/handlers/modtap.py | 23 -- kmk/handlers/sequences.py | 72 ++-- kmk/handlers/stock.py | 220 ++++------ kmk/hid.py | 115 +++++- kmk/keys.py | 81 +--- kmk/kmk_keyboard.py | 384 ++++++++++-------- kmk/kmktime.py | 32 +- kmk/modules/__init__.py | 40 ++ kmk/modules/layers.py | 191 +++++++++ kmk/modules/modtap.py | 57 +++ kmk/modules/power.py | 146 +++++++ kmk/modules/split.py | 308 ++++++++++++++ kmk/preload_imports.py | 37 -- pyproject.toml | 1 + setup.cfg | 3 +- user_keymaps/default/__init__.py | 0 user_keymaps/default/converter/__init__.py | 0 .../converter/fourtypercentclub/__init__.py | 0 .../default/converter/keebio/__init__.py | 0 user_keymaps/default/nice_nano/__init__.py | 0 user_keymaps/default/nice_nano/crkbd.py | 41 -- user_keymaps/dzervas/lab68.py | 3 + user_keymaps/kdb424/corne.py | 71 ++-- user_keymaps/kdb424/gherkin.py | 87 ---- user_keymaps/kdb424/klanck.py | 90 ---- user_keymaps/kdb424/levinson_r2.py | 93 ----- user_keymaps/kdb424/luddite.py | 33 +- user_keymaps/kdb424/nyquist_r2.py | 139 +++---- user_keymaps/klardotsh/iris_r2.py | 30 +- user_keymaps/klardotsh/klarank_featherm4.py | 26 +- user_keymaps/rk463345/levinson_r2.py | 29 +- 140 files changed, 3860 insertions(+), 2312 deletions(-) rename {kmk/boards => boards}/__init__.py (100%) create mode 100644 boards/boardsource/3x4/README.md rename kmk/boards/converter/fourtypercentclub/gherkin.py => boards/boardsource/3x4/kb.py (52%) create mode 100644 boards/boardsource/3x4/main.py create mode 100644 boards/boardsource/4x12/README.md create mode 100644 boards/boardsource/4x12/kb.py create mode 100644 boards/boardsource/4x12/main.py create mode 100644 boards/boardsource/5x12/README.md create mode 100644 boards/boardsource/5x12/kb.py create mode 100644 boards/boardsource/5x12/main.py create mode 100644 boards/boardsource/microdox/README.md create mode 100644 boards/boardsource/microdox/kb.py create mode 100644 boards/boardsource/microdox/main.py create mode 100644 boards/crkbd/README.md rename kmk/boards/nice_nano/crkbd.py => boards/crkbd/kb.py (78%) create mode 100644 boards/crkbd/main.py create mode 100644 boards/ergo_travel/README.md create mode 100644 boards/ergo_travel/kb.py create mode 100644 boards/ergo_travel/main.py rename {kmk/boards/converter => boards/fourtypercentclub}/__init__.py (100%) create mode 100644 boards/fourtypercentclub/gherkin/README.md create mode 100644 boards/fourtypercentclub/gherkin/kb.py create mode 100644 boards/fourtypercentclub/gherkin/main.py create mode 100644 boards/fourtypercentclub/luddite/README.md rename kmk/boards/converter/fourtypercentclub/luddite.py => boards/fourtypercentclub/luddite/converter_kb.py (100%) create mode 100644 boards/fourtypercentclub/luddite/kb.py rename user_keymaps/default/converter/fourtypercentclub/luddite.py => boards/fourtypercentclub/luddite/main.py (82%) create mode 100644 boards/keebio/iris/README.md create mode 100644 boards/keebio/iris/kb.py rename kmk/boards/converter/keebio/iris_r2.py => boards/keebio/iris/kb_converter.py (94%) create mode 100644 boards/keebio/iris/main.py create mode 100644 boards/keebio/levinson/README.md create mode 100644 boards/keebio/levinson/kb.py rename kmk/boards/converter/keebio/levinson_r2.py => boards/keebio/levinson/kb_converter.py (84%) create mode 100644 boards/keebio/levinson/main.py create mode 100644 boards/keebio/nyquist/README.md create mode 100644 boards/keebio/nyquist/kb.py rename kmk/boards/converter/keebio/nyquist_r2.py => boards/keebio/nyquist/kb_converter.py (81%) rename user_keymaps/default/converter/keebio/nyquist_r2.py => boards/keebio/nyquist/main.py (95%) rename {kmk/boards => boards}/klarank.py (93%) create mode 100644 boards/lily58/README.md create mode 100644 boards/lily58/kb.py create mode 100644 boards/lily58/main.py create mode 100644 boards/reviung39/README.md create mode 100644 boards/reviung39/kb.py create mode 100644 boards/reviung39/main.py create mode 100644 boards/reviung41/README.md create mode 100644 boards/reviung41/kb.py create mode 100644 boards/reviung41/main.py create mode 100644 boards/rhymestone/README.md create mode 100644 boards/rhymestone/kb.py create mode 100644 boards/rhymestone/main.py create mode 100644 boards/tg4x/README.md create mode 100644 boards/tg4x/kb.py create mode 100644 boards/tg4x/main.py create mode 100644 docs/Getting_Started.md create mode 100644 docs/Offiially_Supported_Microcontrollers.md create mode 100644 docs/ble_hid.md delete mode 100644 docs/examples.md create mode 100644 docs/extensions.md create mode 100644 docs/handwiring.md delete mode 100644 docs/hardware.md create mode 100644 docs/international.md create mode 100644 docs/layers.md delete mode 100644 docs/leader.md create mode 100644 docs/media_keys.md create mode 100644 docs/modules.md create mode 100644 docs/porting_to_kmk.md create mode 100644 docs/power.md delete mode 100644 kmk/ble.py delete mode 100644 kmk/boards/converter/fourtypercentclub/__init__.py delete mode 100644 kmk/boards/converter/keebio/__init__.py delete mode 100644 kmk/boards/converter/keebio/bdn9.py delete mode 100644 kmk/boards/converter/keebio/fourier.py delete mode 100644 kmk/boards/converter/keebio/iris_r1.py delete mode 100644 kmk/boards/converter/keebio/lapace.py delete mode 100644 kmk/boards/converter/keebio/levinson_r1.py delete mode 100644 kmk/boards/converter/keebio/nyquist_r1.py delete mode 100644 kmk/boards/converter/keebio/quefrency.py delete mode 100644 kmk/boards/converter/keebio/rorschach.py delete mode 100644 kmk/boards/converter/keebio/tragicforce68.py delete mode 100644 kmk/boards/converter/keebio/viterbi_r1.py delete mode 100644 kmk/boards/converter/keebio/viterbi_r2.py delete mode 100644 kmk/boards/converter/lets-split/__init__.py delete mode 100644 kmk/boards/converter/lets-split/lets-split_r1.py delete mode 100644 kmk/boards/converter/lets-split/lets-split_r2.py create mode 100644 kmk/extensions/international.py delete mode 100644 kmk/extensions/leader.py rename kmk/{ => extensions}/led.py (79%) create mode 100644 kmk/extensions/media_keys.py rename kmk/{ => extensions}/rgb.py (60%) delete mode 100644 kmk/extensions/split.py delete mode 100644 kmk/handlers/layers.py delete mode 100644 kmk/handlers/modtap.py create mode 100644 kmk/modules/__init__.py create mode 100644 kmk/modules/layers.py create mode 100644 kmk/modules/modtap.py create mode 100644 kmk/modules/power.py create mode 100644 kmk/modules/split.py delete mode 100644 kmk/preload_imports.py delete mode 100644 user_keymaps/default/__init__.py delete mode 100644 user_keymaps/default/converter/__init__.py delete mode 100644 user_keymaps/default/converter/fourtypercentclub/__init__.py delete mode 100644 user_keymaps/default/converter/keebio/__init__.py delete mode 100644 user_keymaps/default/nice_nano/__init__.py delete mode 100644 user_keymaps/default/nice_nano/crkbd.py delete mode 100644 user_keymaps/kdb424/gherkin.py delete mode 100644 user_keymaps/kdb424/klanck.py delete mode 100644 user_keymaps/kdb424/levinson_r2.py diff --git a/Makefile b/Makefile index e14ddd8..efe4ad4 100644 --- a/Makefile +++ b/Makefile @@ -23,7 +23,7 @@ MPY_TARGET_DIR ?= .compiled PY_KMK_TREE = $(shell find $(MPY_SOURCES) -name "*.py") DIST_DESCRIBE = $(shell $(DIST_DESCRIBE_CMD)) -all: copy-kmk copy-bootpy copy-keymap +all: copy-kmk copy-bootpy copy-keymap copy-board compile: $(MPY_TARGET_DIR)/.mpy.compiled @@ -96,7 +96,7 @@ fix-formatting: devdeps @$(PIPENV) run black . fix-isort: devdeps - @find kmk/ user_keymaps/ -name "*.py" | xargs $(PIPENV) run isort + @find kmk/ user_keymaps/ boards/ -name "*.py" | xargs $(PIPENV) run isort clean: @echo "===> Cleaning build artifacts" @@ -135,6 +135,12 @@ 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" @@ -162,4 +168,10 @@ 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 +endif # BOARD + + endif # MOUNTPOINT diff --git a/README.md b/README.md index 17fad71..21b9802 100644 --- a/README.md +++ b/README.md @@ -34,72 +34,15 @@ file](https://cdn.kmkfw.io/kmk-latest.unoptimized.zip) forms. These follow the `KC.LWIN(KC.L)` to lock the screen on a Windows PC - [Built-in unicode macros, including emojis](https://github.com/KMKfw/kmk_firmware/blob/master/docs/sequences.md) -- [Multiple vim-inspired leader key - modes](https://github.com/KMKfw/kmk_firmware/blob/master/docs/leader.md) - [RGB underglow](https://github.com/KMKfw/kmk_firmware/blob/master/docs/rgb.md) and [LED backlights](https://github.com/KMKfw/kmk_firmware/blob/master/docs/led.md) - One key can turn into many more based on [how many times you tap it](https://github.com/KMKfw/kmk_firmware/blob/master/docs/tapdance.md) - -Coming (hopefully) soon: Bluetooth support! Stay tuned. +- Bluetooth HID and split keyboards. No more wires. ## Getting Started - -- Start by grabbing a supported microcontroller. Broadly speaking, KMK supports - any device CircuitPython does, but KMK requires a decent bit of RAM, and in - general requires a working USB HID stack, which leads us to recommend the - following controllers: - - * [Adafruit ItsyBitsy M4 Express](https://www.adafruit.com/product/3800)\* - * [Adafruit Feather M4 Express](https://www.adafruit.com/product/3857) - * [Adafruit Feather nRF52840 Express](https://www.adafruit.com/product/4062) - * [MakerDiary nRF52840 MDK](https://store.makerdiary.com/collections/frontpage/products/nrf52840-mdk-iot-development-kit) - * [SparkFun Pro nRF52840 Mini](https://www.sparkfun.com/products/15025) - - > \* The ItsyBitsy M4 Express is the only controller we currently support in - > non-handwired configurations, using our [ItsyBitsy to Pro Micro converter - > PCB](https://github.com/KMKfw/kmk_firmware/tree/master/hardware) designed by - > @siddacious and @kdb424. It is our most-recommended MCU until [the ItsyBitsy is - > updated with an nRF52840 - > chip](https://blog.adafruit.com/2019/01/26/comingsoon-itsybitsy-nrf52480-runs-circuitpython-adafruit-circuitpython-adafruit-circuitpython/) - - > Some other controllers, such as the [Feather M0 Express](https://www.adafruit.com/product/3403), - > are usable in reduced functionality modes and may require custom hackery. - > For example, @kdb424 uses a ItsyBitsy M0 Express as a barebones matrix scanner - > in a split keyboard configuration - > [here](https://github.com/KMKfw/kmk_firmware/commit/1f84079dc8aadeb9627c4762d9f9fb855292c4a2). - > Use such controllers at your own risk. - -- Ensure CircuitPython 4.0.0 or newer is installed on your controller. We - recommend the latest stable version from - [circuitpython.org](https://circuitpython.org/downloads). Flashing - instructions vary by device: all Adafruit boards can be flashed [using their - instructions](https://learn.adafruit.com/welcome-to-circuitpython/installing-circuitpython), - other boards generally have their instructions [in the CircuitPython - repository](https://github.com/adafruit/circuitpython) under the - `ports/atmel-samd/boards/` and `ports/nrf/boards/` directories. If all else fails, consult your device's official - documentation. - -- [Download the latest KMK release](https://cdn.kmkfw.io/kmk-latest.zip) and - extract the zip to the USB drive exposed by CircuitPython, typically labeled - `CIRCUITPY`. Again, [we'll defer to Adafruit's - documentation](https://learn.adafruit.com/welcome-to-circuitpython/circuitpython-libraries) - on adding libraries to a CircuitPython installation. You should end up with a - folder called `kmk` and a file called `boot.py`, both living at the top of - this USB drive. - -- Define your keyboard in a file called `main.py` on this `CIRCUITPY` drive and - get tinkering! Examples of both handwired and ProMicro-\>ItsyBitsy converted - boards exist under the `user_keymaps/` tree, and feel free to submit a pull - request of your own definitions! At this point, you'll want to look through - `docs/` in the source tree to explore the functionality at your disposal. - -> Linux, BSD, and MacOS users can also make use of the `Makefile` provided in -> this source tree to flash KMK and a keymap using `rsync`. This is advanced -> functionality outside the scope of this README, but it's documented in the -> `docs/` tree. +Our getting started guide can be found [here](https://github.com/KMKfw/docs/Getting_Started.md) ## The KMK Team diff --git a/kmk/boards/__init__.py b/boards/__init__.py similarity index 100% rename from kmk/boards/__init__.py rename to boards/__init__.py diff --git a/boards/boardsource/3x4/README.md b/boards/boardsource/3x4/README.md new file mode 100644 index 0000000..f7ff40c --- /dev/null +++ b/boards/boardsource/3x4/README.md @@ -0,0 +1,13 @@ +# Boardsource 3x4 + +![Boardsource3x4](https://boardsource.imgix.net/30171267-d988-46cc-ba03-9f6a8ab96487.jpg?raw=true) + +This macro pad / small 12 key was inspired by the plaid look + +kb.py is designed to work with the nice!nano + +Retailers (USA) +[Boardsource](https://boardsource.xyz/store/5ecc2008eee64242946c98c1) + +Extentions enabled by default +- [Layers](https://github.com/KMKfw/kmk_firmware/tree/master/docs/layers.md) Need more keys than switches? Use layers. diff --git a/kmk/boards/converter/fourtypercentclub/gherkin.py b/boards/boardsource/3x4/kb.py similarity index 52% rename from kmk/boards/converter/fourtypercentclub/gherkin.py rename to boards/boardsource/3x4/kb.py index 85f0dc3..2bac698 100644 --- a/kmk/boards/converter/fourtypercentclub/gherkin.py +++ b/boards/boardsource/3x4/kb.py @@ -5,6 +5,8 @@ from kmk.matrix import DiodeOrientation class KMKKeyboard(_KMKKeyboard): - col_pins = (board.D9, board.D10, board.D11, board.D12, board.D13, board.SCL) - row_pins = (board.A3, board.A4, board.A5, board.SCK, board.MOSI) + row_pins = (board.P1_15, board.P0_02, board.P0_29) + col_pins = (board.P0_09, board.P0_10, board.P1_11, board.P1_13) diode_orientation = DiodeOrientation.COLUMNS + i2c = board.I2C + powersave_pin = board.P0_13 diff --git a/boards/boardsource/3x4/main.py b/boards/boardsource/3x4/main.py new file mode 100644 index 0000000..f0be11f --- /dev/null +++ b/boards/boardsource/3x4/main.py @@ -0,0 +1,30 @@ +from kb import KMKKeyboard +from kmk.keys import KC +from kmk.modules.layers import Layers + +keyboard = KMKKeyboard() + +# Cleaner key names +_______ = KC.TRNS +XXXXXXX = KC.NO + +layers_ext = Layers() +keyboard.modules = [layers_ext] + +RAISE = KC.MO(1) + +keyboard.keymap = [ + [ #Base + KC.N0, KC.N1, KC.N4, KC.N7, + KC.ENT, KC.N2, KC.N5, KC.N8, + RAISE, KC.N3, KC.N6, KC.N9 + ], + [ #RAISE + _______, _______, _______, _______, + _______, _______, _______, _______, + _______, _______, _______, _______ + ] +] + +if __name__ == '__main__': + keyboard.go() diff --git a/boards/boardsource/4x12/README.md b/boards/boardsource/4x12/README.md new file mode 100644 index 0000000..35cef12 --- /dev/null +++ b/boards/boardsource/4x12/README.md @@ -0,0 +1,21 @@ +# Boardsource 4x12 Ortho + +![Boardsource4x12](https://boardsource.imgix.net/164c3388-5057-46c8-8fcd-82c58c7870ce.jpg?raw=true) +![Boardsource4x12LP](https://boardsource.imgix.net/c2108ea4-7d70-4327-b4b4-88c8191b1369.jpg?raw=true) + +The 4x12 ortholinear keyboard is an extremely common and beloved layout within the keyboard community. Made popular by Jack's Planck from OLKB, the 4x12 ortholinear layout is possibly the most popular non-stagger layout available. + +kb.py is designed to work with the nice!nano + +Retailers (USA) +4x12 +[Boardsource](https://boardsource.xyz/store/5ecb78d286879c9a0c22dafd ) +Low profile 4x12 +[Boardsource](https://boardsource.xyz/store/5ecb7dad86879c9a0c22db32) + +Extentions enabled by default +- [Layers](https://github.com/KMKfw/kmk_firmware/tree/master/docs/layers.md) Need more keys than switches? Use layers. +- [MediaKeys](https://github.com/KMKfw/kmk_firmware/tree/master/docs/media_keys.md) Control volume and other media functions + +Common Extentions +- [Power](https://github.com/KMKfw/kmk_firmware/tree/master/docs/power.md) Powersaving features for battery life diff --git a/boards/boardsource/4x12/kb.py b/boards/boardsource/4x12/kb.py new file mode 100644 index 0000000..0a2a97e --- /dev/null +++ b/boards/boardsource/4x12/kb.py @@ -0,0 +1,25 @@ +import board + +from kmk.kmk_keyboard import KMKKeyboard as _KMKKeyboard +from kmk.matrix import DiodeOrientation + + +class KMKKeyboard(_KMKKeyboard): + row_pins = (board.P0_08, board.P0_06, board.P0_17, board.P0_20) + col_pins = ( + board.P0_31, + board.P0_29, + board.P0_02, + board.P1_15, + board.P1_13, + board.P1_11, + board.P0_10, + board.P0_09, + board.P1_06, + board.P1_04, + board.P0_11, + board.P1_00, + ) + diode_orientation = DiodeOrientation.COLUMNS + i2c = board.I2C + powersave_pin = board.P0_13 diff --git a/boards/boardsource/4x12/main.py b/boards/boardsource/4x12/main.py new file mode 100644 index 0000000..ea7b407 --- /dev/null +++ b/boards/boardsource/4x12/main.py @@ -0,0 +1,43 @@ +from kb import KMKKeyboard +from kmk.extensions.media_keys import MediaKeys +from kmk.keys import KC +from kmk.modules.layers import Layers + +keyboard = KMKKeyboard() + +media = MediaKeys() +layers_ext = Layers() + +keyboard.extensions = [media] +keyboard.modules = [layers_ext] + +# Cleaner key names +_______ = KC.TRNS +XXXXXXX = KC.NO + +LOWER = KC.MO(1) +RAISE = KC.MO(2) + +keyboard.keymap = [ + [ #QWERTY + KC.TAB, KC.Q, KC.W, KC.E, KC.R, KC.T, KC.Y, KC.U, KC.I, KC.O, KC.P, KC.BSPC, + KC.ESC, 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.ENT , + KC.PIPE, KC.LCTL, KC.LALT, KC.LGUI, LOWER, KC.SPC, KC.SPC, RAISE, KC.LEFT, KC.DOWN, KC.UP, KC.RGHT + ], + [ #LOWER + KC.GRV, KC.N1, KC.N2, KC.N3, KC.N4, KC.N5, KC.N6, KC.N7, KC.N8, KC.N9, KC.N0, KC.BSPC, + KC.DEL, KC.F1, KC.F2, KC.F3, KC.F4, KC.F5, KC.F6, KC.MINS, KC.EQL, KC.LBRC, KC.RBRC, KC.BSLS, + _______, KC.F7, KC.F8, KC.F9, KC.F10, KC.F11, KC.F12, KC.NUHS, KC.NUBS, KC.PGUP, KC.PGDN, _______, + _______, _______, _______, _______, _______, _______, _______, _______, KC.MNXT, KC.VOLD, KC.VOLU, KC.MPLY + ], + [ #RAISE + KC.TILD, KC.EXLM, KC.AT, KC.HASH, KC.DLR, KC.PERC, KC.CIRC, KC.AMPR, KC.ASTR, KC.LPRN, KC.RPRN, KC.BSPC, + KC.DEL, KC.F1, KC.F2, KC.F3, KC.F4, KC.F5, KC.F6, KC.UNDS, KC.PLUS, KC.LCBR, KC.RCBR, KC.PIPE, + _______, KC.F7, KC.F8, KC.F9, KC.F10, KC.F11, KC.F12, _______, _______, KC.HOME, KC.END, _______, + _______, _______, _______, _______, _______, _______, _______, _______, KC.MNXT, KC.VOLD, KC.VOLU, KC.MPLY + ] +] + +if __name__ == '__main__': + keyboard.go() diff --git a/boards/boardsource/5x12/README.md b/boards/boardsource/5x12/README.md new file mode 100644 index 0000000..7195bcc --- /dev/null +++ b/boards/boardsource/5x12/README.md @@ -0,0 +1,21 @@ +# Boardsource 5x12 Ortho + +![Boardsource5x12](https://boardsource.imgix.net/74abb511-792e-42d9-9f6e-8100c521b2e0.jpg?raw=true) +![Boardsource5x12LP](https://boardsource.imgix.net/57ad3f69-3c88-4ae8-9592-6e4d2f45a58e.jpg?raw=true) + +5x12 ortholinear -- for when just really don't want to give up your number row. The 5x12 ortholinear keyboard is a common ortholinear layout that many people prefer because it includes a number row. Made popular by Jack's Preonic from OLKB, the 5x12 ortholinear layout is a great option for those who want to try ortholinear but feel they aren't ready to make the jump to a 40%. The 5x12 Ortho is an approachable keyboard with hotswap compatibility. + +kb.py is designed to work with the nice!nano + +Retailers (USA) +5x12 +[Boardsource](https://boardsource.xyz/store/5ecb802c86879c9a0c22db61) +Low Profile 5x12 +[Boardsource](https://boardsource.xyz/store/5ecb822386879c9a0c22db84) + +Extentions enabled by default +- [Layers](https://github.com/KMKfw/kmk_firmware/tree/master/docs/layers.md) Need more keys than switches? Use layers. +- [MediaKeys](https://github.com/KMKfw/kmk_firmware/tree/master/docs/media_keys.md) Control volume and other media functions + +Common Extentions +- [Power](https://github.com/KMKfw/kmk_firmware/tree/master/docs/power.md) Powersaving features for battery life diff --git a/boards/boardsource/5x12/kb.py b/boards/boardsource/5x12/kb.py new file mode 100644 index 0000000..fb2bc99 --- /dev/null +++ b/boards/boardsource/5x12/kb.py @@ -0,0 +1,25 @@ +import board + +from kmk.kmk_keyboard import KMKKeyboard as _KMKKeyboard +from kmk.matrix import DiodeOrientation + + +class KMKKeyboard(_KMKKeyboard): + row_pins = (board.P0_08, board.P0_06, board.P0_17, board.P0_20, board.P0_22) + col_pins = ( + board.P0_31, + board.P0_29, + board.P0_02, + board.P1_15, + board.P1_13, + board.P1_11, + board.P0_10, + board.P0_09, + board.P1_06, + board.P1_04, + board.P0_11, + board.P1_00, + ) + diode_orientation = DiodeOrientation.COLUMNS + i2c = board.I2C + powersave_pin = board.P0_13 diff --git a/boards/boardsource/5x12/main.py b/boards/boardsource/5x12/main.py new file mode 100644 index 0000000..217985c --- /dev/null +++ b/boards/boardsource/5x12/main.py @@ -0,0 +1,46 @@ +from kb import KMKKeyboard +from kmk.extensions.media_keys import MediaKeys +from kmk.keys import KC +from kmk.modules.layers import Layers + +keyboard = KMKKeyboard() + +media = MediaKeys() +layers_ext = Layers() + +keyboard.modules = [layers_ext] +keyboard.extensions = [media] + +# Cleaner key names +_______ = KC.TRNS +XXXXXXX = KC.NO + +LOWER = KC.MO(1) +RAISE = KC.MO(2) + +keyboard.keymap = [ + [ #QWERTY + KC.GRV, KC.N1, KC.N2, KC.N3, KC.N4, KC.N5, KC.N6, KC.N7, KC.N8, KC.N9, KC.N0, KC.BSPC, + KC.TAB, KC.Q, KC.W, KC.E, KC.R, KC.T, KC.Y, KC.U, KC.I, KC.O, KC.P, KC.DEL, + KC.ESC, 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.ENT, + KC.PIPE, KC.LCTL, KC.LALT, KC.LGUI, LOWER, KC.SPC, KC.SPC, RAISE, KC.LEFT, KC.DOWN, KC.UP, KC.RGHT + ], + [ #LOWER + KC.ESC, KC.F1, KC.F2, KC.F3, KC.F4, KC.F5, KC.F6, KC.F7, KC.F8, KC.F9, KC.F10, KC.F11, + _______, _______, _______, _______, _______, _______, _______, _______, KC.UP, _______, _______, _______, + _______, _______, _______, _______, _______, _______, _______, KC.LEFT, KC.DOWN, KC.RGHT, _______, _______, + KC.CAPS, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, _______, _______, _______, KC.MNXT, KC.VOLD, KC.VOLU, KC.MPLY + ], + [ #RAISE + KC.GRV, KC.F1, KC.F2, KC.F3, KC.F4, KC.F5, KC.F6, KC.F7, KC.F8, KC.F9, KC.F10, KC.F11, + KC.ESC, KC.N1, KC.N2, KC.N3, KC.N4, KC.N5, KC.N6, KC.N7, KC.N8, KC.N9, KC.N0, KC.DEL, + _______, KC.N4, KC.N5, KC.N6, KC.PLUS, KC.F5, KC.F6, KC.MINS, KC.EQL, KC.LBRC, KC.RBRC, _______, + KC.ENT, KC.N7, KC.N8, KC.N9, KC.MINS, KC.F11, KC.F12, KC.NUHS, KC.NUBS, KC.MUTE, _______, KC.BSLS, + _______, _______, _______, _______, _______, _______, _______, _______, KC.MNXT, KC.VOLD, KC.VOLU, KC.MPLY + ] +] + +if __name__ == '__main__': + keyboard.go() diff --git a/boards/boardsource/microdox/README.md b/boards/boardsource/microdox/README.md new file mode 100644 index 0000000..cec0c53 --- /dev/null +++ b/boards/boardsource/microdox/README.md @@ -0,0 +1,19 @@ +# Microdox + +![microdox](https://boardsource.imgix.net/337ae65a-d061-46a4-b119-9916b043c58f.jpg?raw=true) + +The Microdox is is a feature-packed 30% split columnar staggered keyboard. Even though the Microdox is an extremely small keyboard it offers tons of features from larger boards while maintaining a tiny footprint. + +kb.py is designed to work with the nice!nano + +Retailers (USA) +[Boardsource](https://boardsource.xyz/store/5f2e7e4a2902de7151494f92) + +Extentions enabled by default +- [Layers](https://github.com/KMKfw/kmk_firmware/tree/master/docs/layers.md) Need more keys than switches? Use layers. +- [BLE_Split](https://github.com/KMKfw/kmk_firmware/tree/master/docs/split.md) Connects halves without wires +- [ModTap](https://github.com/KMKfw/kmk_firmware/tree/master/docs/modtap.md) Allows mod keys to act as different keys when tapped. + +Common Extentions +- [Split](https://github.com/KMKfw/kmk_firmware/tree/master/docs/split.md) Connects halves using a wire +- [Power](https://github.com/KMKfw/kmk_firmware/tree/master/docs/power.md) Powersaving features for battery life diff --git a/boards/boardsource/microdox/kb.py b/boards/boardsource/microdox/kb.py new file mode 100644 index 0000000..2727465 --- /dev/null +++ b/boards/boardsource/microdox/kb.py @@ -0,0 +1,24 @@ +import board + +from kmk.kmk_keyboard import KMKKeyboard as _KMKKeyboard +from kmk.matrix import DiodeOrientation +from kmk.matrix import intify_coordinate as ic + + +class KMKKeyboard(_KMKKeyboard): + col_pins = (board.P0_31, board.P0_29, board.P0_02, board.P1_15, board.P1_13) + row_pins = (board.P0_10, board.P0_09, board.P1_04, board.P1_06) + diode_orientation = DiodeOrientation.COLUMNS + data_pin = board.P0_08 + rgb_pixel_pin = board.P0_06 + rgb_num_pixels = 12 + i2c = board.I2C + powersave_pin = board.P0_13 + + coord_mapping = [] + coord_mapping.extend(ic(0, x) for x in range(10)) + coord_mapping.extend(ic(1, x) for x in range(10)) + coord_mapping.extend(ic(2, x) for x in range(10)) + + # And now, to handle R3, which at this point is down to just six keys + coord_mapping.extend(ic(3, x) for x in range(3, 9)) diff --git a/boards/boardsource/microdox/main.py b/boards/boardsource/microdox/main.py new file mode 100644 index 0000000..bcb94db --- /dev/null +++ b/boards/boardsource/microdox/main.py @@ -0,0 +1,54 @@ +from kb import KMKKeyboard +from kmk.keys import KC +from kmk.modules.layers import Layers +from kmk.modules.split import Split, SplitSide, SplitType + +keyboard = KMKKeyboard() + +# TODO Comment one of these on each side +split_side = SplitSide.LEFT +split_side = SplitSide.RIGHT +split = Split(split_type=SplitType.BLE, split_side=split_side) + +layers_ext = Layers() + +keyboard.modules = [layers_ext, split] + +# Cleaner key names +_______ = KC.TRNS +XXXXXXX = KC.NO + +LOWER = KC.MO(2) +RAISE = KC.MO(1) + +RGB_TOG = KC.RGB_TOG +RGB_HUI = KC.RGB_HUI +RGB_HUD = KC.RGB_HUI +RGB_SAI = KC.RGB_SAI +RGB_SAD = KC.RGB_SAD +RGB_VAI = KC.RGB_VAI +RGB_VAD = KC.RGB_VAD + +keyboard.keymap = [ + [ #QWERTY + KC.Q, KC.W, KC.E, KC.R, KC.T, KC.Y, KC.U, KC.I, KC.O, KC.P,\ + KC.A, KC.S, KC.D, KC.F, KC.G, KC.H, KC.J, KC.K, KC.L, KC.SCLN,\ + KC.Z, KC.X, KC.C, KC.V, KC.B, KC.N, KC.M, KC.COMM, KC.DOT, KC.SLSH,\ + KC.LCTL, LOWER, KC.SPC, KC.BSPC, RAISE, KC.ENT, + ], + [ #RAISE + KC.N1, KC.N2, KC.N3, KC.N4, KC.N5, KC.N6, KC.N7, KC.N8, KC.N9, KC.N0,\ + KC.TAB, KC.LEFT, KC.DOWN, KC.UP, KC.RGHT, XXXXXXX, KC.MINS, KC.EQL, KC.LBRC, KC.RBRC,\ + KC.LCTL, KC.GRV, KC.LGUI, KC.LALT, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC.BSLS, KC.QUOT,\ + XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, + ], + [ #LOWER + KC.EXLM, KC.AT, KC.HASH, KC.DLR, KC.PERC, KC.CIRC, KC.AMPR, KC.ASTR, KC.LPRN, KC.RPRN,\ + KC.ESC, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC.UNDS, KC.PLUS, KC.LCBR, KC.RCBR,\ + KC.CAPS, KC.TILD, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC.PIPE, KC.DQT,\ + XXXXXXX, XXXXXXX, XXXXXXX, KC.ENT, XXXXXXX, KC.DEL + ] +] + +if __name__ == '__main__': + keyboard.go() diff --git a/boards/crkbd/README.md b/boards/crkbd/README.md new file mode 100644 index 0000000..d9fa431 --- /dev/null +++ b/boards/crkbd/README.md @@ -0,0 +1,27 @@ +# Corne Keyboard (CRKBD) + +![Crkbd](https://boardsource.imgix.net/a90342e3-caa0-467c-bebd-d17f031d5210.jpg?raw=true) + +![Crkbd](https://boardsource.imgix.net/9cbd31b7-3b37-42c6-919e-3be35a2578f6.jpg?raw=true) + +A split keyboard with a 3x6 collumnar stagger and 3 thumb keys. + +kb.py is designed to work with the nice!nano + +Hardware Availability: [PCB & Case Source](https://github.com/foostan/crkbd) + +Retailers (USA) +Corne +[Boardsource](https://boardsource.xyz/store/5ecc0f81eee64242946c988f) + +Corne LP +[Boardsource](https://boardsource.xyz/store/5f2efc462902de7151495057) + +Extentions enabled by default +- [Layers](https://github.com/KMKfw/kmk_firmware/tree/master/docs/layers.md) Need more keys than switches? Use layers. +- [RGB](https://github.com/KMKfw/kmk_firmware/tree/master/docs/rgb.md) Light it up +- [BLE_Split](https://github.com/KMKfw/kmk_firmware/tree/master/docs/split.md) Connects halves without wires + +Common Extentions +- [Split](https://github.com/KMKfw/kmk_firmware/tree/master/docs/split.md) Connects halves using a wire +- [Power](https://github.com/KMKfw/kmk_firmware/tree/master/docs/power.md) Powersaving features for battery life diff --git a/kmk/boards/nice_nano/crkbd.py b/boards/crkbd/kb.py similarity index 78% rename from kmk/boards/nice_nano/crkbd.py rename to boards/crkbd/kb.py index b1bafc3..c93b487 100644 --- a/kmk/boards/nice_nano/crkbd.py +++ b/boards/crkbd/kb.py @@ -16,13 +16,10 @@ class KMKKeyboard(_KMKKeyboard): ) row_pins = (board.P0_22, board.P0_24, board.P1_00, board.P0_11) diode_orientation = DiodeOrientation.COLUMNS - - split_type = 'UART' # TODO add bluetooth support as well - split_flip = True - split_offsets = [6, 6, 6, 6, 6] - uart_pin = board.P0_08 + data_pin = board.P0_08 rgb_pixel_pin = board.P0_06 - extra_data_pin = board.SDA # TODO This is incorrect. Find better solution + i2c = board.I2C + powersave_pin = board.P0_13 coord_mapping = [] coord_mapping.extend(ic(0, x) for x in range(12)) diff --git a/boards/crkbd/main.py b/boards/crkbd/main.py new file mode 100644 index 0000000..3723479 --- /dev/null +++ b/boards/crkbd/main.py @@ -0,0 +1,67 @@ +from kb import KMKKeyboard, rgb_pixel_pin +from kmk.extensions.rgb import RGB +from kmk.keys import KC +from kmk.modules.layers import Layers +from kmk.modules.split import Split, SplitSide, SplitType + +keyboard = KMKKeyboard() + +# Adding extentions +rgb = RGB(pixel_pin=rgb_pixel_pin, num_pixels=27, val_limit=100, hue_default=190, sat_default=100, val_default=5) + +# TODO Comment one of these on each side +split_side = SplitSide.LEFT +split_side = SplitSide.RIGHT +split = Split(split_type=SplitType.BLE, split_side=split_side) + +layers_ext = Layers() + +keyboard.modules = [layers_ext, split] +keyboard.extensions = [rgb] +# +# Cleaner key names +_______ = KC.TRNS +XXXXXXX = KC.NO + +LOWER = KC.MO(1) +RAISE = KC.MO(2) +ADJUST = KC.LT(3, KC.SPC) + +RGB_TOG = KC.RGB_TOG +RGB_HUI = KC.RGB_HUI +RGB_HUD = KC.RGB_HUI +RGB_SAI = KC.RGB_SAI +RGB_SAD = KC.RGB_SAD +RGB_VAI = KC.RGB_VAI +RGB_VAD = KC.RGB_VAD + + +keyboard.keymap = [ + [ #QWERTY + KC.TAB, KC.Q, KC.W, KC.E, KC.R, KC.T, KC.Y, KC.U, KC.I, KC.O, KC.P, KC.BSPC,\ + KC.LCTL, KC.A, KC.S, KC.D, KC.F, KC.G, KC.H, KC.J, KC.K, KC.L, KC.SCLN, KC.QUOT,\ + KC.LSFT, KC.Z, KC.X, KC.C, KC.V, KC.B, KC.N, KC.M, KC.COMM, KC.DOT, KC.SLSH, KC.RSFT,\ + KC.LGUI, LOWER, ADJUST, KC.ENT, RAISE, KC.RALT, + ], + [ #LOWER + KC.ESC, KC.N1, KC.N2, KC.N3, KC.N4, KC.N5, KC.N6, KC.N7, KC.N8, KC.N9, KC.N0, KC.BSPC,\ + KC.LCTL, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC.LEFT, KC.DOWN, KC.UP, KC.RIGHT, XXXXXXX, XXXXXXX,\ + KC.LSFT, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,\ + KC.LGUI, LOWER, ADJUST, KC.ENT, RAISE, KC.RALT, + ], + [ #RAISE + KC.ESC, KC.EXLM, KC.AT, KC.HASH, KC.DLR, KC.PERC, KC.CIRC, KC.AMPR, KC.ASTR, KC.LPRN, KC.RPRN, KC.BSPC,\ + KC.LCTL, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC.MINS, KC.EQL, KC.LCBR, KC.RCBR, KC.PIPE, KC.GRV,\ + KC.LSFT, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC.UNDS, KC.PLUS, KC.LBRC, KC.RBRC, KC.BSLS, KC.TILD,\ + KC.LGUI, LOWER, ADJUST, KC.ENT, RAISE, KC.RALT, + ], + [ #ADJUST + RGB_TOG, RGB_HUI, RGB_SAI, RGB_VAI, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,\ + XXXXXXX, RGB_HUD, RGB_SAD, RGB_VAD, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,\ + XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,\ + KC.LGUI, LOWER, ADJUST, KC.ENT, RAISE, KC.RALT, + ] +] + +if __name__ == '__main__': + keyboard.go() diff --git a/boards/ergo_travel/README.md b/boards/ergo_travel/README.md new file mode 100644 index 0000000..226d902 --- /dev/null +++ b/boards/ergo_travel/README.md @@ -0,0 +1,21 @@ +# Ergo Travel + +![ergo_travel](https://boardsource.imgix.net/fa53de62-fd37-4c75-8c5b-b4bec37927c1.jpg?raw=true) + +As the name implies, the Ergo Travel was originally designed as a travel keyboard, but it works just as well on your desk as a main daily use keyboard. The Ergo Travel is a popular choice by many because it offers a few more keys than other keyboards in similar sizes, and that is why we chose to stock it. Additionally, the Ergo Travel has nice customization options in the thumb cluster because you can configure the main thumb key to use a single larger 2u key, or two smaller 1u keys depending on your preference. The clean and simple aesthetic of the Ergo Travel and the few extra keys make it an awesome option for people wanting a 40%-ish split keyboard. + +kb.py is designed to work with the nice!nano + +Hardware Availability: [PCB & Case Source](https://github.com/jpconstantineau/ErgoTravel/blob/master/OrderingInstructions.md) + +Retailers (USA) +[Boardsource](https://boardsource.xyz/store/5eed23430883e03ef9a69d6a) + +Extentions enabled by default +- [Layers](https://github.com/KMKfw/kmk_firmware/tree/master/docs/layers.md) Need more keys than switches? Use layers. +- [BLE_Split](https://github.com/KMKfw/kmk_firmware/tree/master/docs/split.md) Connects halves without wires +- [MediaKeys](https://github.com/KMKfw/kmk_firmware/tree/master/docs/media_keys.md) Control volume and other media functions + +Common Extentions +- [Split](https://github.com/KMKfw/kmk_firmware/tree/master/docs/split.md) Connects halves using a wire +- [Power](https://github.com/KMKfw/kmk_firmware/tree/master/docs/power.md) Powersaving features for battery life diff --git a/boards/ergo_travel/kb.py b/boards/ergo_travel/kb.py new file mode 100644 index 0000000..92798f2 --- /dev/null +++ b/boards/ergo_travel/kb.py @@ -0,0 +1,33 @@ +import board + +from kmk.kmk_keyboard import KMKKeyboard as _KMKKeyboard +from kmk.matrix import DiodeOrientation +from kmk.matrix import intify_coordinate as ic + + +class KMKKeyboard(_KMKKeyboard): + row_pins = (board.P0_24, board.P1_00, board.P0_11, board.P1_04) + col_pins = ( + board.P0_29, + board.P0_02, + board.P1_15, + board.P1_13, + board.P1_11, + board.P0_10, + board.P0_09, + ) + diode_orientation = DiodeOrientation.COLUMNS + led_pin = board.P1_06 + rgb_pixel_pin = board.P0_06 + rgb_num_pixels = 12 + data_pin = board.P0_08 + i2c = board.I2C + powersave_pin = board.P0_13 + + coord_mapping = [] + coord_mapping.extend(ic(0, x) for x in range(14)) + coord_mapping.extend(ic(1, x) for x in range(14)) + coord_mapping.extend(ic(2, x) for x in range(14)) + + # And now, to handle R3, which at this point is down to just six keys + coord_mapping.extend(ic(3, x) for x in range(3, 12)) diff --git a/boards/ergo_travel/main.py b/boards/ergo_travel/main.py new file mode 100644 index 0000000..da76a4b --- /dev/null +++ b/boards/ergo_travel/main.py @@ -0,0 +1,58 @@ +from kb import KMKKeyboard +from kmk.extensions.media_keys import MediaKeys +from kmk.keys import KC +from kmk.modules.layers import Layers +from kmk.modulessplit import Split, SplitSide, SplitType + +keyboard = KMKKeyboard() + +# TODO Comment one of these on each side +split_side = SplitSide.LEFT +split_side = SplitSide.RIGHT +split = Split(split_type=SplitType.BLE, split_side=split_side) + +media = MediaKeys() +layers_ext = Layers() +keyboard.modules = [layers_ext, split] +keyboard.extensions = (media) + +# Cleaner key names +_______ = KC.TRNS +XXXXXXX = KC.NO + +LOWER = KC.MO(1) +RAISE = KC.MO(2) +ADJUST = KC.MO(3) + +CALTDEL = KC.LCTL(KC.LALT(KC.DEL)) +TSKMGR = KC.LCTL(KC.LSFT(KC.KC_ESC)) + +keyboard.keymap = [ + [ #QWERTY + KC.ESC, KC.Q, KC.W, KC.E, KC.R, KC.T, KC.MINS, KC.EQL, 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.LBRC, KC.RBRC, 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.SPC, KC.SPC, KC.N, KC.M, KC.COMM, KC.DOT, KC.SLSH, KC.ENT,\ + KC.LCTL, KC.LGUI, KC.LALT, ADJUST, LOWER, KC.SPC, KC.SPC, RAISE, KC.LEFT, KC.UP, KC.DOWN, KC.RGHT\ + ], + [ #LOWER + KC.TILD, KC.EXLM, KC.AT, KC.HASH, KC.DLR, KC.PERC, KC.HOME, KC.PGUP, KC.CIRC, KC.AMPR, KC.ASTR, KC.LPRN, KC.RPRN, KC.DEL,\ + _______, KC.F1, KC.F2, KC.F3, KC.F4, KC.F5, KC.END , KC.PGDN, KC.F6, KC.UNDS, KC.PLUS, KC.LCBR, KC.RCBR, KC.BSLS,\ + _______, KC.F7, KC.F8, KC.F9, KC.F10, KC.F11, KC.BSPC, KC.BSPC, KC.F12, _______, _______, KC.MUTE, _______, KC.PIPE,\ + _______, _______, _______, _______, _______, KC.BSPC, KC.BSPC, _______, KC.MNXT, KC.VOLD, KC.VOLU, KC.MPLY\ + ], + [ #RAISE + KC.ESC, KC.N1, KC.N2, KC.N3, KC.N4, KC.N5, _______, _______, KC.N6, KC.N7, KC.N8, KC.N9, KC.N0, KC.DEL, \ + _______, KC.N4, KC.N5, KC.N6, KC.PLUS, _______, _______, _______, _______, KC.MINS, KC.EQL, KC.LBRC, KC.RBRC, _______, \ + KC.ENT, KC.N7, KC.N8, KC.N9, KC.MINS, _______, _______, _______, _______, KC.NUHS, KC.NUBS, KC.MUTE, _______, KC.BSLS, \ + _______, KC.COMM, KC.N0, KC.DOT, _______, KC.BSPC, KC.BSPC, _______, KC.MNXT, KC.VOLD, KC.VOLU, KC.MPLY \ + ], + [ #ADJUST + TSKMGR, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, CALTDEL, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, + ] +] + +if __name__ == '__main__': + keyboard.go() diff --git a/kmk/boards/converter/__init__.py b/boards/fourtypercentclub/__init__.py similarity index 100% rename from kmk/boards/converter/__init__.py rename to boards/fourtypercentclub/__init__.py diff --git a/boards/fourtypercentclub/gherkin/README.md b/boards/fourtypercentclub/gherkin/README.md new file mode 100644 index 0000000..30641a5 --- /dev/null +++ b/boards/fourtypercentclub/gherkin/README.md @@ -0,0 +1,17 @@ +# Ghirkin + +![Gherkin](https://4.bp.blogspot.com/-sQ18-lNZXOc/WCzlTde-4PI/AAAAAAAB_JQ/qQrehAMG6DMKf3i4oj4mkmLGOfTUvb3KgCLcB/s640/IMG_20161116_122926.jpg) + +A keyboard with only 30 keys. + +kb.py is designed to work with the nice!nano + +Hardware Availability: [Gherkin project on 40% Keyboards](http://www.40percent.club/2016/11/gherkin.html) + +Extentions enabled by default +- [Layers](https://github.com/KMKfw/kmk_firmware/tree/master/docs/layers.md) Need more keys than switches? Use layers. +- [ModTap](https://github.com/KMKfw/kmk_firmware/tree/master/docs/modtap.md) Allows mod keys to act as different keys when tapped. +- [LED](https://github.com/KMKfw/kmk_firmware/tree/master/docs/led.md) Light your keys up + +Common Extentions +- [Power](https://github.com/KMKfw/kmk_firmware/tree/master/docs/power.md) Powersaving features for battery life diff --git a/boards/fourtypercentclub/gherkin/kb.py b/boards/fourtypercentclub/gherkin/kb.py new file mode 100644 index 0000000..c00bc22 --- /dev/null +++ b/boards/fourtypercentclub/gherkin/kb.py @@ -0,0 +1,21 @@ +import board + +from kmk.kmk_keyboard import KMKKeyboard as _KMKKeyboard +from kmk.matrix import DiodeOrientation + + +class KMKKeyboard(_KMKKeyboard): + row_pins = (board.P1_15, board.P1_13, board.P1_11, board.P0_10, board.P0_09) + col_pins = ( + board.P1_04, + board.P0_11, + board.P1_00, + board.P0_24, + board.P0_22, + board.P0_20, + ) + diode_orientation = DiodeOrientation.COLUMNS + led_pin = board.P1_06 + rgb_num_pixels = 0 + i2c = board.I2C + powersave_pin = board.P0_13 diff --git a/boards/fourtypercentclub/gherkin/main.py b/boards/fourtypercentclub/gherkin/main.py new file mode 100644 index 0000000..5245c12 --- /dev/null +++ b/boards/fourtypercentclub/gherkin/main.py @@ -0,0 +1,67 @@ +from kb import KMKKeyboard +from kmk.extensions.led import LED +from kmk.keys import KC +from kmk.modules.layers import Layers +from kmk.modules.modtap import ModTap + +keyboard = KMKKeyboard() + + +modtap = ModTap() +layers_ext = Layers() +led = LED() +keyboard.extensions = [led] +keyboard.modules = [layers_ext, modtap] + +# Cleaner key names +_______ = KC.TRNS +XXXXXXX = KC.NO + +FN1_SPC = KC.LT(1, KC.SPC) +FN2_BSPC = KC.LT(2, KC.BSPC) +FN3_C = KC.LT(3, KC.C) +FN4_V = KC.LT(4, KC.V) +FN5_B = KC.LT(5, KC.B) +CTL_Z = KC.CTL_T(KC.Z) +ALT_X = KC.ALT(KC.X) +ALT_N = KC.ALT(KC.N) +CTL_M = KC.CTL(KC.M) +SFT_ENT = KC.SFT(KC.ENT) +BL_DEC = KC.BL_DEC +BL_INC = KC.BL_INC + +keyboard.keymap = [ + [ + KC.Q, KC.W, KC.E, KC.R, KC.T, KC.Y, KC.U, KC.I, KC.O, KC.P, + KC.A, KC.S, KC.D, KC.F, KC.G, KC.H, KC.J, KC.K, KC.L, KC.ESC, + CTL_Z, ALT_X, FN3_C, FN4_V, FN2_BSPC, FN1_SPC, FN5_B, ALT_N, CTL_M, SFT_ENT + ], + [ + KC.N1, KC.N2, KC.N3, KC.N4, KC.N5, KC.N6, KC.N7, KC.N8, KC.N9, KC.N0, + KC.F1, KC.F2, KC.F3, KC.F4, KC.F5, KC.F6, KC.F7, KC.F8, KC.F9, KC.F10, + _______, _______, _______, _______, KC.DEL, _______, _______, _______, _______, _______ + ], + [ + KC.EXLM, KC.AT, KC.HASH, KC.DLR, KC.PERC, KC.CIRC, KC.AMPR, KC.ASTR, KC.LPRN, KC.RPRN, + KC.F11, KC.F12, _______, _______, _______, _______, _______, _______, _______, KC.GRV, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ + ], + [ + _______, _______, _______, _______, _______, KC.MINS, KC.EQL, KC.LBRC, KC.RBRC, KC.BSLS, + KC.TAB, _______, _______, _______, _______, KC.COMM, KC.DOT, KC.SLSH, KC.SCLN, KC.QUOT, + _______, _______, _______, _______, _______, _______, KC.LEFT, KC.DOWN, KC.UP, KC.RGHT + ], + [ + _______, _______, _______, _______, _______, KC.UNDS, KC.PLUS, KC.LCBR, KC.RCBR, KC.PIPE, + KC.TAB, _______, _______, _______, _______, KC.LABK, KC.RABK, KC.QUES, KC.COLN, KC.DQUO, + _______, _______, _______, _______, _______, _______, KC.HOME, KC.PGDN, KC.PGUP, KC.END + ], + [ + KC.CALC, KC.WHOM, KC.MAIL, KC.MYCM, _______, _______, _______, _______, _______, KC.PSCR, + _______, _______, _______, _______, _______, _______, _______, _______, BL_DEC, BL_INC, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ + ] +] + +if __name__ == '__main__': + keyboard.go() diff --git a/boards/fourtypercentclub/luddite/README.md b/boards/fourtypercentclub/luddite/README.md new file mode 100644 index 0000000..d4f16cd --- /dev/null +++ b/boards/fourtypercentclub/luddite/README.md @@ -0,0 +1,18 @@ +# Luddite + +![Luddite](https://1.bp.blogspot.com/-GAAa-sMU_WU/W7uYLJJ8x1I/AAAAAAACS44/31n2z69BSboM4KT48YkNMJRYciC8LUMWgCLcBGAs/s640/a.jpg) + +Luddite 60% keyboard with backlight and RGB underglow. + +kb.py is designed to work with the nice!nano +kb_converter.py is designed to work with an itsybitsy with converter board found [here](https://github.com/KMKfw/kmk_firmware/tree/master/hardware) + +Hardware Availability: [Luddite project on 40% Keyboards](http://www.40percent.club/search/label/luddite) + +Extentions enabled by default +- [Layers](https://github.com/KMKfw/kmk_firmware/tree/master/docs/layers.md) Need more keys than switches? Use layers. +- [RGB](https://github.com/KMKfw/kmk_firmware/tree/master/docs/rgb.md) RGB underglow +- [LED](https://github.com/KMKfw/kmk_firmware/tree/master/docs/led.md) Light your keys up + +Common Extentions +- [Power](https://github.com/KMKfw/kmk_firmware/tree/master/docs/power.md) Powersaving features for battery life diff --git a/kmk/boards/converter/fourtypercentclub/luddite.py b/boards/fourtypercentclub/luddite/converter_kb.py similarity index 100% rename from kmk/boards/converter/fourtypercentclub/luddite.py rename to boards/fourtypercentclub/luddite/converter_kb.py diff --git a/boards/fourtypercentclub/luddite/kb.py b/boards/fourtypercentclub/luddite/kb.py new file mode 100644 index 0000000..1846fae --- /dev/null +++ b/boards/fourtypercentclub/luddite/kb.py @@ -0,0 +1,33 @@ +import board + +from kmk.kmk_keyboard import KMKKeyboard as _KMKKeyboard +from kmk.matrix import DiodeOrientation + + +class KMKKeyboard(_KMKKeyboard): + row_pins = ( + board.P0_06, + board.P0_08, + board.P0_17, + board.P0_20, + board.P0_22, + board.P0_24, + board.P1_00, + board.P0_11, + ) + col_pins = ( + board.P0_31, + board.P0_29, + board.P0_02, + board.P1_15, + board.P1_13, + board.P1_11, + board.P0_10, + board.P0_09, + ) + diode_orientation = DiodeOrientation.COLUMNS + led_pin = board.P1_06 + rgb_pixel_pin = board.P1_04 + rgb_num_pixels = 8 + i2c = board.I2C + powersave_pin = board.P0_13 diff --git a/user_keymaps/default/converter/fourtypercentclub/luddite.py b/boards/fourtypercentclub/luddite/main.py similarity index 82% rename from user_keymaps/default/converter/fourtypercentclub/luddite.py rename to boards/fourtypercentclub/luddite/main.py index ec9ffff..7d7c4f3 100644 --- a/user_keymaps/default/converter/fourtypercentclub/luddite.py +++ b/boards/fourtypercentclub/luddite/main.py @@ -1,11 +1,20 @@ -from kmk.boards.converter.fourtypercentclub.luddite import KMKKeyboard +from kb import KMKKeyboard +from kmk.extensions.led import LED +from kmk.extensions.rgb import RGB from kmk.keys import KC +from kmk.modules.layers import Layers keyboard = KMKKeyboard() _______ = KC.TRNS XXXXXXX = KC.NO +rgb_ext = RGB(pixel_pin=keyboard.rgb_pixel_pin, num_pixels=keyboard.rgb_num_pixels) +led = LED() +layers_ext = Layers() +keyboard.extensions = [rgb_ext, led] +keyboard.modules = [layers_ext] + BASE = 0 FN1 = 1 diff --git a/boards/keebio/iris/README.md b/boards/keebio/iris/README.md new file mode 100644 index 0000000..ae2a07c --- /dev/null +++ b/boards/keebio/iris/README.md @@ -0,0 +1,15 @@ +# Iris Rev 2 + +A split keyboard with a 4x6 layout with additional 4 thumb buttons + +kb.py is designed to work with the nice!nano +kb_converter.py is designed to work with an itsybitsy with converter board found [here](https://github.com/KMKfw/kmk_firmware/tree/master/hardware) + +Extentions enabled by default +- [Layers](https://github.com/KMKfw/kmk_firmware/tree/master/docs/layers.md) Need more keys than switches? Use layers. +- [RGB](https://github.com/KMKfw/kmk_firmware/tree/master/docs/rgb.md) Light it up +- [BLE_Split](https://github.com/KMKfw/kmk_firmware/tree/master/docs/split.md) Connects halves without wires + +Common Extentions +- [Split](https://github.com/KMKfw/kmk_firmware/tree/master/docs/split.md) Connects halves using a wire +- [Power](https://github.com/KMKfw/kmk_firmware/tree/master/docs/power.md) Powersaving features for battery life diff --git a/boards/keebio/iris/kb.py b/boards/keebio/iris/kb.py new file mode 100644 index 0000000..8bb1c56 --- /dev/null +++ b/boards/keebio/iris/kb.py @@ -0,0 +1,43 @@ +import board + +from kmk.kmk_keyboard import KMKKeyboard as _KMKKeyboard +from kmk.matrix import DiodeOrientation +from kmk.matrix import intify_coordinate as ic + + +class KMKKeyboard(_KMKKeyboard): + row_pins = (board.P1_00, board.P0_11, board.P1_04, board.P0_08, board.P0_22) + col_pins = ( + board.P0_02, + board.P1_15, + board.P1_13, + board.P1_11, + board.P0_10, + board.P0_09, + ) + diode_orientation = DiodeOrientation.COLUMNS + led_pin = board.P1_06 + rgb_pixel_pin = board.P0_06 + rgb_num_pixels = 12 + i2c = board.I2C + data_pin = board.P0_08 + powersave_pin = board.P0_13 + led_pin = board.D7 + + coord_mapping = [] + coord_mapping.extend(ic(0, x) for x in range(12)) + coord_mapping.extend(ic(1, x) for x in range(12)) + coord_mapping.extend(ic(2, x) for x in range(12)) + + # Buckle up friends, the bottom row of this keyboard is wild, and making + # our layouts match, visually, what the keyboard looks like, requires some + # surgery on the bottom two rows of coords + + # Row index 3 is actually perfectly sane and we _could_ expose it + # just like the above three rows, however, visually speaking, the + # top-right thumb cluster button (when looking at the left-half PCB) + # is more inline with R3, so we'll jam that key (and its mirror) in here + coord_mapping.extend(ic(3, x) for x in range(6)) + coord_mapping.append(ic(4, 2)) + coord_mapping.append(ic(4, 9)) + coord_mapping.extend(ic(3, x) for x in range(6, 12)) # Now, the rest of R3 diff --git a/kmk/boards/converter/keebio/iris_r2.py b/boards/keebio/iris/kb_converter.py similarity index 94% rename from kmk/boards/converter/keebio/iris_r2.py rename to boards/keebio/iris/kb_converter.py index 651b407..80f5bb5 100644 --- a/kmk/boards/converter/keebio/iris_r2.py +++ b/boards/keebio/iris/kb_converter.py @@ -16,8 +16,10 @@ class KMKKeyboard(_KMKKeyboard): split_flip = True split_offsets = (6, 6, 6, 6, 6) split_type = 'UART' - uart_pin = board.SCL - extra_data_pin = board.SDA + data_pin = board.SCL + data_pin2 = board.SDA + rgb_num_pixels = 12 + i2c = board.I2C rgb_pixel_pin = board.TX led_pin = board.D7 diff --git a/boards/keebio/iris/main.py b/boards/keebio/iris/main.py new file mode 100644 index 0000000..ea89652 --- /dev/null +++ b/boards/keebio/iris/main.py @@ -0,0 +1,95 @@ +from kb import KMKKeyboard +from kmk.consts import UnicodeMode +from kmk.extensions.rgb import RGB +from kmk.handlers.sequences import compile_unicode_string_sequences as cuss +from kmk.handlers.sequences import send_string +from kmk.keys import KC +from kmk.modules.layers import Layers +from kmk.modules.split import Split, SplitSide, SplitType + +keyboard = KMKKeyboard() + +keyboard.debug_enabled = False +keyboard.unicode_mode = UnicodeMode.LINUX +keyboard.tap_time = 750 + +emoticons = cuss({ + # Emojis + 'BEER': r'🍺', + 'BEER_TOAST': r'🍻', + 'FACE_CUTE_SMILE': r'😊', + 'FACE_HEART_EYES': r'😍', + 'FACE_JOY': r'😂', + 'FACE_SWEAT_SMILE': r'😅', + 'FACE_THINKING': r'🤔', + 'FIRE': r'🔥', + 'FLAG_CA': r'🇨🇦', + 'FLAG_US': r'🇺🇸', + 'HAND_CLAP': r'👏', + 'HAND_HORNS': r'🤘', + 'HAND_OK': r'👌', + 'HAND_THUMB_DOWN': r'👎', + 'HAND_THUMB_UP': r'👍', + 'HAND_WAVE': r'👋', + 'HEART': r'❤️', + 'MAPLE_LEAF': r'🍁', + 'POOP': r'💩', + 'TADA': r'🎉', + 'SHRUG_EMOJI': r'🤷', + + # Emoticons, but fancier + 'ANGRY_TABLE_FLIP': r'(ノಠ痊ಠ)ノ彡┻━┻', + 'CELEBRATORY_GLITTER': r'+。:.゚ヽ(´∀。)ノ゚.:。+゚゚+。:.゚ヽ(*´∀)ノ゚.:。+゚', + 'SHRUGGIE': r'¯\_(ツ)_/¯', + 'TABLE_FLIP': r'(╯°□°)╯︵ ┻━┻', +}) + +WPM = send_string('Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Bibendum arcu vitae elementum curabitur vitae nunc sed. Facilisis sed odio morbi quis.') + +_______ = KC.TRNS +xxxxxxx = KC.NO +HELLA_TD = KC.TD( + KC.A, + KC.B, + send_string('macros in a tap dance? I think yes'), + KC.TG(1), +) + +rgb_ext = RGB(pixel_pin=keyboard.rgb_pixel_pin, num_pixels=keyboard.rgb_num_pixels) +layers_ext = Layers() + +# TODO Comment one of these on each side +split_side = SplitSide.LEFT +split_side = SplitSide.RIGHT +split = Split(split_type=SplitType.BLE, split_side=split_side) + +keyboard.extensions = [rgb_ext] +keyboard.modules = [split, layers_ext] + + +keyboard.keymap = [ + [ + KC.GESC, KC.N1, KC.N2, KC.N3, KC.N4, KC.N5, KC.N6, KC.N7, KC.N8, KC.N9, KC.N0, KC.BSPC, + KC.TAB, KC.QUOT, KC.COMM, KC.DOT, KC.P, KC.Y, KC.F, KC.G, KC.C, KC.R, KC.L, KC.SLSH, + KC.LGUI, KC.A, KC.O, KC.E, KC.U, KC.I, KC.D, KC.H, KC.T, KC.N, KC.S, KC.ENTER, + KC.LCTL, KC.SCLN, KC.Q, KC.J, KC.K, KC.X, KC.MO(2), KC.MO(1), KC.B, KC.M, KC.W, KC.V, KC.Z, KC.LALT, + KC.LEFT, KC.RGHT, KC.LSFT, KC.SPC, KC.UP, KC.DOWN, + ], + [ + _______, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, KC.F10, KC.F11, KC.F12, xxxxxxx, xxxxxxx, _______, + xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, KC.F7, KC.F8, KC.F9, xxxxxxx, xxxxxxx, KC.EQUAL, + xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, KC.INS, KC.F4, KC.F5, KC.F6, xxxxxxx, xxxxxxx, xxxxxxx, + xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, KC.NO, _______, KC.F1, KC.F2, KC.F3, xxxxxxx, xxxxxxx, _______, + KC.HOME, KC.END, _______, xxxxxxx, KC.PGUP, KC.PGDN, + ], + [ + KC.MUTE, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, KC.LBRC, KC.RBRC, KC.DEL, + xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, KC.BSLS, + KC.RGUI, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, KC.MINS, + xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, _______, KC.VOLU, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, KC.RALT, + KC.HOME, KC.END, _______, KC.VOLD, KC.PGUP, KC.PGDN, + ], +] + +if __name__ == '__main__': + keyboard.go() diff --git a/boards/keebio/levinson/README.md b/boards/keebio/levinson/README.md new file mode 100644 index 0000000..af15c9b --- /dev/null +++ b/boards/keebio/levinson/README.md @@ -0,0 +1,15 @@ +# Levinson Rev 2 + +A split keyboard with a 4x6 layout + +kb.py is designed to work with the nice!nano +kb_converter.py is designed to work with an itsybitsy with converter board found [here](https://github.com/KMKfw/kmk_firmware/tree/master/hardware) + +Extentions enabled by default +- [Layers](https://github.com/KMKfw/kmk_firmware/tree/master/docs/layers.md) Need more keys than switches? Use layers. +- [RGB](https://github.com/KMKfw/kmk_firmware/tree/master/docs/rgb.md) Light it up +- [BLE_Split](https://github.com/KMKfw/kmk_firmware/tree/master/docs/split.md) Connects halves without wires + +Common Extentions +- [Split](https://github.com/KMKfw/kmk_firmware/tree/master/docs/split.md) Connects halves using a wire +- [Power](https://github.com/KMKfw/kmk_firmware/tree/master/docs/power.md) Powersaving features for battery life diff --git a/boards/keebio/levinson/kb.py b/boards/keebio/levinson/kb.py new file mode 100644 index 0000000..d546211 --- /dev/null +++ b/boards/keebio/levinson/kb.py @@ -0,0 +1,23 @@ +import board + +from kmk.kmk_keyboard import KMKKeyboard as _KMKKeyboard +from kmk.matrix import DiodeOrientation + + +class KMKKeyboard(_KMKKeyboard): + row_pins = (board.P0_22, board.P1_00, board.P0_11, board.P1_04) + col_pins = ( + board.P0_02, + board.P1_15, + board.P1_13, + board.P1_11, + board.P0_10, + board.P0_09, + ) + diode_orientation = DiodeOrientation.COLUMNS + rgb_pixel_pin = board.P0_06 + rgb_num_pixels = 12 + led_pin = board.P1_06 + data_pin = board.P0_08 + i2c = board.I2C + powersave_pin = board.P0_13 diff --git a/kmk/boards/converter/keebio/levinson_r2.py b/boards/keebio/levinson/kb_converter.py similarity index 84% rename from kmk/boards/converter/keebio/levinson_r2.py rename to boards/keebio/levinson/kb_converter.py index 1626821..3c43c9f 100644 --- a/kmk/boards/converter/keebio/levinson_r2.py +++ b/boards/keebio/levinson/kb_converter.py @@ -12,7 +12,7 @@ class KMKKeyboard(_KMKKeyboard): split_type = 'UART' split_flip = True split_offsets = [6, 6, 6, 6, 6] - uart_pin = board.SCL - extra_data_pin = board.SDA + data_pin = board.SCL + data_pin2 = board.SDA rgb_pixel_pin = board.TX - # led_pin = board.D7 + led_pin = board.D7 diff --git a/boards/keebio/levinson/main.py b/boards/keebio/levinson/main.py new file mode 100644 index 0000000..da6a790 --- /dev/null +++ b/boards/keebio/levinson/main.py @@ -0,0 +1,132 @@ +from kb import KMKKeyboard +from kmk.extensions.rgb import RGB +from kmk.keys import KC +from kmk.modules.layers import Layers +from kmk.modules.split import Split, SplitSide, SplitType + +keyboard = KMKKeyboard() + +rgb_ext = RGB(pixel_pin=keyboard.rgb_pixel_pin, num_pixels=keyboard.rgb_num_pixels) +layers_ext = Layers() +# TODO Comment one of these on each side +split_side = SplitSide.LEFT +split_side = SplitSide.RIGHT +split = Split(split_type=SplitType.BLE, split_side=split_side) + +keyboard.extensions = [rgb_ext] +keyboard.modules = [layers_ext, split] + +_______ = KC.TRNS +XXXXXXX = KC.NO + +LOWER = KC.MO(3) +RAISE = KC.MO(4) +ADJUST = KC.MO(5) + +keyboard.keymap = [ + # Qwerty + # ,-----------------------------------------------------------------------------------. + # | Tab | Q | W | E | R | T | Y | U | I | O | P | Bak | + # |------+------+------+------+------+-------------+------+------+------+------+------| + # | Esc | A | S | D | F | G | H | J | K | L | ; | " | + # |------+------+------+------+------+------|------+------+------+------+------+------| + # | Shift| Z | X | C | V | B | N | M | , | . | / |Enter | + # |------+------+------+------+------+------+------+------+------+------+------+------| + # |Adjust| Ctrl | Alt | GUI |Lower |Space |Space |Raise | Left | Down | Up |Right | + # `-----------------------------------------------------------------------------------' + [ + KC.TAB, KC.Q, KC.W, KC.E, KC.R, KC.T, KC.Y, KC.U, KC.I, KC.O, KC.P, KC.BSPC, + KC.GESC, 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.ENT, + ADJUST, KC.LCTL, KC.LALT, KC.LGUI, LOWER, KC.SPC, KC.SPC, RAISE, KC.LEFT, KC.DOWN, KC.UP, KC.RGHT, + ], + + # Colemak + # ,-----------------------------------------------------------------------------------. + # | Tab | Q | W | F | P | G | J | L | U | Y | ; | Bak | + # |------+------+------+------+------+-------------+------+------+------+------+------| + # | Esc | A | R | S | T | D | H | N | E | I | O | " | + # |------+------+------+------+------+------|------+------+------+------+------+------| + # | Shift| Z | X | C | V | B | K | M | , | . | / |Enter | + # |------+------+------+------+------+------+------+------+------+------+------+------| + # |Adjust| Ctrl | Alt | GUI |Lower |Space |Space |Raise | Left | Down | Up |Right | + # `-----------------------------------------------------------------------------------' + [ + KC.TAB, KC.Q, KC.W, KC.F, KC.P, KC.G, KC.J, KC.L, KC.U, KC.Y, KC.SCLN, KC.BSPC, + KC.GESC, KC.A, KC.R, KC.S, KC.T, KC.D, KC.H, KC.N, KC.E, KC.I, KC.O, KC.QUOT, + KC.LSFT, KC.Z, KC.X, KC.C, KC.V, KC.B, KC.K, KC.M, KC.COMM, KC.DOT, KC.SLSH, KC.ENT, + ADJUST, KC.LCTL, KC.LALT, KC.LGUI, LOWER, KC.SPC, KC.SPC, RAISE, KC.LEFT, KC.DOWN, KC.UP, KC.RGHT, + ], + + # Dvorak + # ,-----------------------------------------------------------------------------------. + # | Tab | " | , | . | P | Y | F | G | C | R | L | Bak | + # |------+------+------+------+------+-------------+------+------+------+------+------| + # | Esc | A | O | E | U | I | D | H | T | N | S | / | + # |------+------+------+------+------+------|------+------+------+------+------+------| + # | Shift| ; | Q | J | K | X | B | M | W | V | Z |Enter | + # |------+------+------+------+------+------+------+------+------+------+------+------| + # |Adjust| Ctrl | Alt | GUI |Lower |Space |Space |Raise | Left | Down | Up |Right | + # `-----------------------------------------------------------------------------------' + [ + KC.TAB, KC.QUOT, KC.COMM, KC.DOT, KC.P, KC.Y, KC.F, KC.G, KC.C, KC.R, KC.L, KC.BSPC, + KC.GESC, KC.A, KC.O, KC.E, KC.U, KC.I, KC.D, KC.H, KC.T, KC.N, KC.S, KC.SLSH, + KC.LSFT, KC.SCLN, KC.Q, KC.J, KC.K, KC.X, KC.B, KC.M, KC.W, KC.V, KC.Z, KC.ENT, + ADJUST, KC.LCTL, KC.LALT, KC.LGUI, LOWER, KC.SPC, KC.SPC, RAISE, KC.LEFT, KC.DOWN, KC.UP, KC.RGHT, + ], + + # Lower + # ,-----------------------------------------------------------------------------------. + # | ~ | ! | @ | # | $ | % | ^ | & | * | ( | ) | Del | + # |------+------+------+------+------+-------------+------+------+------+------+------| + # | Del | F1 | F2 | F3 | F4 | F5 | F6 | . | + | | \ | | | + # |------+------+------+------+------+------|------+------+------+------+------+------| + # | | F7 | F8 | F9 | F10 | F11 | F12 |ISO ~ |ISO | | | |Enter | + # |------+------+------+------+------+------+------+------+------+------+------+------| + # | | | | | | | | Next | Vol- | Vol+ | Play | + # `-----------------------------------------------------------------------------------' + [ + KC.TILD, KC.EXLM, KC.AT, KC.HASH, KC.DLR, KC.PERC, KC.CIRC, KC.AMPR, KC.ASTR, KC.LPRN, KC.RPRN, KC.DEL, + KC.DEL, KC.F1, KC.F2, KC.F3, KC.F4, KC.F5, KC.F6, KC.UNDS, KC.PLUS, KC.LCBR, KC.RCBR, KC.PIPE, + _______, KC.F7, KC.F8, KC.F9, KC.F10, KC.F11, KC.F12, KC.NUHS, KC.NUBS, _______, _______, _______, + _______, _______, _______, _______, _______, _______, _______, _______, KC.MNXT, KC.VOLD, KC.VOLU, KC.MPLY, + ], + + # Raise + # ,-----------------------------------------------------------------------------------. + # | ` | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | Del | + # |------+------+------+------+------+-------------+------+------+------+------+------| + # | Del | F1 | F2 | F3 | F4 | F5 | F6 | - | = | [ | ] | \ | + # |------+------+------+------+------+------|------+------+------+------+------+------| + # | | F7 | F8 | F9 | F10 | F11 | F12 |ISO # |ISO / | | |Enter | + # |------+------+------+------+------+------+------+------+------+------+------+------| + # | | | | | | | | Next | Vol- | Vol+ | Play | + # `-----------------------------------------------------------------------------------' + [ + KC.GRV, KC.N1, KC.N2, KC.N3, KC.N4, KC.N5, KC.N6, KC.N7, KC.N8, KC.N9, KC.N0, KC.DEL, + KC.DEL, KC.F1, KC.F2, KC.F3, KC.F4, KC.F5, KC.F6, KC.MINS, KC.EQL, KC.LBRC, KC.RBRC, KC.BSLS, + _______, KC.F7, KC.F8, KC.F9, KC.F10, KC.F11, KC.F12, KC.NUHS, KC.NUBS, _______, _______, _______, + _______, _______, _______, _______, _______, _______, _______, _______, KC.MNXT, KC.VOLD, KC.VOLU, KC.MPLY, + ], + + # Adjust + # ,-----------------------------------------------------------------------------------. + # | | Reset|RGB Tg|RGB Md|Hue Up|Hue Dn|Sat Up|Sat Dn|Val Up|Val Dn| | Del | + # |------+------+------+------+------+-------------+------+------+------+------+------| + # | | | | | | | |Qwerty|Colemk|Dvorak| | | + # |------+------+------+------+------+------|------+------+------+------+------+------| + # | | | | | | | | | | | | | + # |------+------+------+------+------+------+------+------+------+------+------+------| + # | | | | | | | | | | | | + # `-----------------------------------------------------------------------------------' + [ + _______, _______, KC.RGB.TOG, KC.RGB.MOD, KC.RGB.HUD, KC.RGB.HUI, KC.RGB.SAD, KC.RGB.SAI, KC.RGB.VAD, KC.RGB.VAI, _______, KC.DEL, + _______, _______, _______, _______, _______, _______, _______, KC.DF(0), KC.DF(1), KC.DF(2), _______, _______, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, + ], + +] + +if __name__ == '__main__': + keyboard.go() diff --git a/boards/keebio/nyquist/README.md b/boards/keebio/nyquist/README.md new file mode 100644 index 0000000..b567df0 --- /dev/null +++ b/boards/keebio/nyquist/README.md @@ -0,0 +1,16 @@ +# Nyquist Rev 2 + +A split keyboard with a 5x6 layout + +kb.py is designed to work with the nice!nano +kb_converter.py is designed to work with an itsybitsy with converter board found [here](https://github.com/KMKfw/kmk_firmware/tree/master/hardware) + + +Extentions enabled by default +- [Layers](https://github.com/KMKfw/kmk_firmware/tree/master/docs/layers.md) Need more keys than switches? Use layers. +- [RGB](https://github.com/KMKfw/kmk_firmware/tree/master/docs/rgb.md) Light it up +- [BLE_Split](https://github.com/KMKfw/kmk_firmware/tree/master/docs/split.md) Connects halves without wires + +Common Extentions +- [Split](https://github.com/KMKfw/kmk_firmware/tree/master/docs/split.md) Connects halves using a wire +- [Power](https://github.com/KMKfw/kmk_firmware/tree/master/docs/power.md) Powersaving features for battery life diff --git a/boards/keebio/nyquist/kb.py b/boards/keebio/nyquist/kb.py new file mode 100644 index 0000000..b3e24ef --- /dev/null +++ b/boards/keebio/nyquist/kb.py @@ -0,0 +1,23 @@ +import board + +from kmk.kmk_keyboard import KMKKeyboard as _KMKKeyboard +from kmk.matrix import DiodeOrientation + + +class KMKKeyboard(_KMKKeyboard): + row_pins = (board.P0_22, board.P1_00, board.P0_11, board.P1_04, board.P1_06) + col_pins = ( + board.P0_08, + board.P0_29, + board.P0_02, + board.P1_15, + board.P1_13, + board.P1_11, + ) + diode_orientation = DiodeOrientation.COLUMNS + rgb_pixel_pin = board.P0_06 + rgb_num_pixels = 12 + data_pin = board.P0_08 + led_pin = board.P0_09 + i2c = board.I2C + powersave_pin = board.P0_13 diff --git a/kmk/boards/converter/keebio/nyquist_r2.py b/boards/keebio/nyquist/kb_converter.py similarity index 81% rename from kmk/boards/converter/keebio/nyquist_r2.py rename to boards/keebio/nyquist/kb_converter.py index 708e09b..b3f90f0 100644 --- a/kmk/boards/converter/keebio/nyquist_r2.py +++ b/boards/keebio/nyquist/kb_converter.py @@ -11,7 +11,7 @@ class KMKKeyboard(_KMKKeyboard): split_type = 'UART' split_flip = True - split_offsets = [6, 6, 6, 6, 6] - uart_pin = board.SCL + data_pin = board.SCL + rgb_num_pixels = 12 rgb_pixel_pin = board.TX - extra_data_pin = board.SDA + data_pin2 = board.SDA diff --git a/user_keymaps/default/converter/keebio/nyquist_r2.py b/boards/keebio/nyquist/main.py similarity index 95% rename from user_keymaps/default/converter/keebio/nyquist_r2.py rename to boards/keebio/nyquist/main.py index 860ff0c..6dc570e 100644 --- a/user_keymaps/default/converter/keebio/nyquist_r2.py +++ b/boards/keebio/nyquist/main.py @@ -1,8 +1,22 @@ -from kmk.boards.converter.keebio.nyquist_r2 import KMKKeyboard +from kb import KMKKeyboard +from kmk.extensions.rgb import RGB from kmk.keys import KC +from kmk.modules.layers import Layers +from kmk.modules.split import Split, SplitSide, SplitType keyboard = KMKKeyboard() +rgb_ext = RGB(pixel_pin=keyboard.rgb_pixel_pin, num_pixels=keyboard.rgb_num_pixels) +layers_ext = Layers() + +# TODO Comment one of these on each side +split_side = SplitSide.LEFT +split_side = SplitSide.RIGHT +split = Split(split_type=SplitType.BLE, split_side=split_side) + +keyboard.modules = [layers_ext, split] +keyboard.extensions = [rgb_ext] + _______ = KC.TRNS XXXXXXX = KC.NO diff --git a/kmk/boards/klarank.py b/boards/klarank.py similarity index 93% rename from kmk/boards/klarank.py rename to boards/klarank.py index 7827f86..8ca7a2c 100644 --- a/kmk/boards/klarank.py +++ b/boards/klarank.py @@ -3,6 +3,7 @@ import board from kmk.kmk_keyboard import KMKKeyboard as _KMKKeyboard from kmk.matrix import DiodeOrientation from kmk.matrix import intify_coordinate as ic +from kmk.modules.layers import Layers # Implements what used to be handled by KMKKeyboard.swap_indicies for this # board, by flipping various row3 (bottom physical row) keys so their @@ -40,3 +41,6 @@ class KMKKeyboard(_KMKKeyboard): coord_mapping.extend(ic(1, x) for x in range(12)) coord_mapping.extend(ic(2, x) for x in range(12)) coord_mapping.extend(ic(3, r3_swap(x)) for x in range(12)) + + layers_ext = Layers() + modules = [layers_ext] diff --git a/boards/lily58/README.md b/boards/lily58/README.md new file mode 100644 index 0000000..d820bd3 --- /dev/null +++ b/boards/lily58/README.md @@ -0,0 +1,20 @@ +# Lily 58 Pro + +![Lily58](https://boardsource.imgix.net/af3d8d6d-5fbe-4578-a2ba-d09d7686fb29.jpg?raw=true) + +The Lily58 is a 58 key split keyboard design by kata0510, featuring a 6x4 columnar stagger and 4 thumb cluster keys on each hand. The Lily58 is a perfect choice for people who want to be on a split keyboard but still want to have a fairly standard amount of keys. + +Hardware Availability: [PCB & Case Source](https://github.com/kata0510/Lily58) +kb.py is designed to work with the nice!nano + +Retailers (USA) +[Boardsource](https://boardsource.xyz/store/5ec9df84c6b834480de6c3d0) + +Extentions enabled by default +- [Layers](https://github.com/KMKfw/kmk_firmware/tree/master/docs/layers.md) Need more keys than switches? Use layers. +- [RGB](https://github.com/KMKfw/kmk_firmware/tree/master/docs/rgb.md) Light it up +- [BLE_Split](https://github.com/KMKfw/kmk_firmware/tree/master/docs/split.md) Connects halves without wires + +Common Extentions +- [Split](https://github.com/KMKfw/kmk_firmware/tree/master/docs/split.md) Connects halves using a wire +- [Power](https://github.com/KMKfw/kmk_firmware/tree/master/docs/power.md) Powersaving features for battery life diff --git a/boards/lily58/kb.py b/boards/lily58/kb.py new file mode 100644 index 0000000..78d0cb5 --- /dev/null +++ b/boards/lily58/kb.py @@ -0,0 +1,32 @@ +import board + +from kmk.kmk_keyboard import KMKKeyboard as _KMKKeyboard +from kmk.matrix import DiodeOrientation +from kmk.matrix import intify_coordinate as ic + + +class KMKKeyboard(_KMKKeyboard): + col_pins = ( + board.P0_31, + board.P0_29, + board.P0_02, + board.P1_15, + board.P1_13, + board.P1_11, + ) + row_pins = (board.P0_22, board.P0_24, board.P1_00, board.P0_11) + diode_orientation = DiodeOrientation.COLUMNS + uart_pin = board.P0_08 + rgb_pixel_pin = board.P0_06 + data_pin = board.P0_08 + i2c = board.I2C + powersave_pin = board.P0_13 + + coord_mapping = [] + coord_mapping.extend(ic(0, x) for x in range(12)) + coord_mapping.extend(ic(1, x) for x in range(12)) + coord_mapping.extend(ic(2, x) for x in range(12)) + coord_mapping.extend(ic(3, x) for x in range(12)) + + # And now, to handle R4, which at this point is down to just ten keys + coord_mapping.extend(ic(4, x) for x in range(1, 11)) diff --git a/boards/lily58/main.py b/boards/lily58/main.py new file mode 100644 index 0000000..3396075 --- /dev/null +++ b/boards/lily58/main.py @@ -0,0 +1,66 @@ +from kb import KMKKeyboard, rgb_pixel_pin +from kmk.extensions.ble_split import BLE_Split +from kmk.extensions.layers import Layers +from kmk.extensions.rgb import RGB +from kmk.keys import KC + +keyboard = KMKKeyboard() + +# Cleaner key names +_______ = KC.TRNS +XXXXXXX = KC.NO + +LOWER = KC.MO(1) +RAISE = KC.MO(2) +ADJUST = KC.LT(3, KC.SPC) + +RGB_TOG = KC.RGB_TOG +RGB_HUI = KC.RGB_HUI +RGB_HUD = KC.RGB_HUI +RGB_SAI = KC.RGB_SAI +RGB_SAD = KC.RGB_SAD +RGB_VAI = KC.RGB_VAI +RGB_VAD = KC.RGB_VAD + +# Adding extentions +rgb = RGB(pixel_pin=rgb_pixel_pin, num_pixels=27, val_limit=100, hue_default=190, sat_default=100, val_default=5) + +# TODO Comment one of these on each side +# Left is 0, Right is 1 +split_side = 0 +split_side = 1 +split = BLE_Split(split_side=split_side) + +layers_ext = Layers() + +extensions = [layers_ext, split, rgb] + +keyboard.keymap = [ + [ #QWERTY + KC.TAB, KC.Q, KC.W, KC.E, KC.R, KC.T, KC.Y, KC.U, KC.I, KC.O, KC.P, KC.BSPC,\ + KC.LCTL, KC.A, KC.S, KC.D, KC.F, KC.G, KC.H, KC.J, KC.K, KC.L, KC.SCLN, KC.QUOT,\ + KC.LSFT, KC.Z, KC.X, KC.C, KC.V, KC.B, KC.N, KC.M, KC.COMM, KC.DOT, KC.SLSH, KC.RSFT,\ + KC.LGUI, LOWER, ADJUST, KC.ENT, RAISE, KC.RALT, + ], + [ #LOWER + KC.ESC, KC.N1, KC.N2, KC.N3, KC.N4, KC.N5, KC.N6, KC.N7, KC.N8, KC.N9, KC.N0, KC.BSPC,\ + KC.LCTL, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC.LEFT, KC.DOWN, KC.UP, KC.RIGHT, XXXXXXX, XXXXXXX,\ + KC.LSFT, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,\ + KC.LGUI, LOWER, ADJUST, KC.ENT, RAISE, KC.RALT, + ], + [ #RAISE + KC.ESC, KC.EXLM, KC.AT, KC.HASH, KC.DLR, KC.PERC, KC.CIRC, KC.AMPR, KC.ASTR, KC.LPRN, KC.RPRN, KC.BSPC,\ + KC.LCTL, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC.MINS, KC.EQL, KC.LCBR, KC.RCBR, KC.PIPE, KC.GRV,\ + KC.LSFT, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC.UNDS, KC.PLUS, KC.LBRC, KC.RBRC, KC.BSLS, KC.TILD,\ + KC.LGUI, LOWER, ADJUST, KC.ENT, RAISE, KC.RALT, + ], + [ #ADJUST + RGB_TOG, RGB_HUI, RGB_SAI, RGB_VAI, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,\ + XXXXXXX, RGB_HUD, RGB_SAD, RGB_VAD, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,\ + XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,\ + KC.LGUI, LOWER, ADJUST, KC.ENT, RAISE, KC.RALT, + ] +] + +if __name__ == '__main__': + keyboard.go() diff --git a/boards/reviung39/README.md b/boards/reviung39/README.md new file mode 100644 index 0000000..65bcf0f --- /dev/null +++ b/boards/reviung39/README.md @@ -0,0 +1,20 @@ +# Reviung39 + +![Reviung39](https://boardsource.imgix.net/d6215164-6100-4b72-b355-1a67b7704463.jpg?raw=true) + +Reviung39 is a 39 key keyboard designed by gtips. The Reviung39 sits somewhere between an Atreus and a Corne, you get some nice ergonomic benefits based on its quasi-split design and since a true split keyboard isn't for everyone, this is an awesome middle ground. I find this keyboard extremely comfortable to use. + +kb.py is designed to work with the nice!nano + +Hardware Availability: [PCB & Case Data](https://github.com/gtips/reviung) + +Retailers (USA) +[Boardsource](https://boardsource.xyz/store/5ecb734486879c9a0c22dab3) + +Extentions enabled by default +- [Layers](https://github.com/KMKfw/kmk_firmware/tree/master/docs/layers.md) Need more keys than switches? Use layers. +- [RGB](https://github.com/KMKfw/kmk_firmware/tree/master/docs/rgb.md) Light it up +- [ModTap](https://github.com/KMKfw/kmk_firmware/tree/master/docs/modtap.md) Allows mod keys to act as different keys when tapped. + +Common Extentions +- [Power](https://github.com/KMKfw/kmk_firmware/tree/master/docs/power.md) Powersaving features for battery life diff --git a/boards/reviung39/kb.py b/boards/reviung39/kb.py new file mode 100644 index 0000000..b7dc3f4 --- /dev/null +++ b/boards/reviung39/kb.py @@ -0,0 +1,27 @@ +import board + +from kmk.kmk_keyboard import KMKKeyboard as _KMKKeyboard +from kmk.matrix import DiodeOrientation + + +class KMKKeyboard(_KMKKeyboard): + row_pins = ( + board.P0_31, + board.P0_29, + board.P0_02, + board.P1_15, + board.P1_13, + board.P1_11, + board.P0_10, + ) + col_pins = ( + board.P0_22, + board.P0_24, + board.P1_00, + board.P0_11, + board.P1_04, + board.P1_06, + ) + diode_orientation = DiodeOrientation.COLUMNS + i2c = board.I2C + powersave_pin = board.P0_13 diff --git a/boards/reviung39/main.py b/boards/reviung39/main.py new file mode 100644 index 0000000..5144f81 --- /dev/null +++ b/boards/reviung39/main.py @@ -0,0 +1,48 @@ +from kb import KMKKeyboard +from kmk.extensions.rgb import RGB +from kmk.keys import KC +from kmk.modules.layers import Layers +from kmk.modules.modtap import ModTap + +keyboard = KMKKeyboard() + +# Adding extentions +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() +layers_ext = Layers() + +keyboard.modules = [layers_ext, modtap] +keyboard.extensions = [rgb] + +# Cleaner key names +_______ = KC.TRNS +XXXXXXX = KC.NO + +LOWER = KC.MO(1) +RAISE = KC.MO(2) + +keyboard.keymap = [ + [ #QWERTY + KC.ESC, KC.N1, KC.N2, KC.N3, KC.N4, KC.N5, KC.N6, KC.N7, KC.N8, KC.N9, KC.N0, KC.GRV, + KC.TAB, KC.Q, KC.W, KC.E, KC.R, KC.T, KC.Y, KC.U, KC.I, KC.O, KC.P, KC.MINS, + KC.LCTRL, 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.LBRC, KC.RBRC, KC.N, KC.M, KC.COMM, KC.DOT, KC.SLSH, KC.RSFT, + KC.LALT, KC.LGUI, LOWER, KC.SPC, KC.ENT, RAISE, KC.BSPC, KC.RGUI + ], + [ #LOWER + KC.F1, KC.F2, KC.F3, KC.F4, KC.F5, KC.F6, KC.F7, KC.F8, KC.F9, KC.F10, KC.F11, KC.F12, + KC.GRV, KC.EXLM, KC.AT, KC.HASH, KC.DLR, KC.PERC, KC.CIRC, KC.AMPR, KC.ASTR, KC.LPRN, KC.RPRN, KC.TILD, + _______, _______, _______, _______, _______, _______, _______, _______, XXXXXXX, KC.UNDS, KC.PLUS, KC.LCBR, KC.RCBR, KC.PIPE, + _______, _______, _______, _______, _______, _______, _______, _______ + ], + [ #RAISE + KC.GRV, KC.N1, KC.N2, KC.N3, KC.N4, KC.N5, KC.N6, KC.N7, KC.N8, KC.N9, KC.N0, _______, + KC.F1, KC.F2, KC.F3, KC.F4, KC.F5, KC.F6, XXXXXXX, KC.LEFT, KC.DOWN, KC.UP, KC.RGHT, XXXXXXX, + KC.F7, KC.F8, KC.F9, KC.F10, KC.F11, KC.F12, _______, _______, KC.PLUS, KC.MINS, KC.EQL, KC.LBRC, KC.RBRC, KC.BSLS, + _______, _______, _______, _______, _______, _______, _______, _______ + ] +] + +if __name__ == '__main__': + keyboard.go() diff --git a/boards/reviung41/README.md b/boards/reviung41/README.md new file mode 100644 index 0000000..2b415a7 --- /dev/null +++ b/boards/reviung41/README.md @@ -0,0 +1,20 @@ +# Reviung41 + +![Reviung41](https://boardsource.imgix.net/ea77f3f8-6cc4-4cb4-a801-cf58b5af8fcc.jpg?raw=true) + +The Reviung41 is a 41 key keyboard designed by gtips, it is a slightly larger version of the popular Reviung 39. These "split non-split" keyboards offer a lot of features split keyboards have in terms of comfort and ergonomics but do so in a single-piece package. Many people consider keyboards in this style easier to travel with since you don't have to manage two halves and there is of course no need for a TRRS cable. This board sits somewhere between and Atreus and Corne, and it is extremely comfortable to use. + +kb.py is designed to work with the nice!nano + +Hardware Availability: [PCB & Case Data](https://github.com/gtips/reviung/tree/master/reviung41) + +Retailers (USA) +[Boardsource](https://boardsource.xyz/store/5f2ef1b52bf5e8714a60f613) + +Extentions enabled by default +- [Layers](https://github.com/KMKfw/kmk_firmware/tree/master/docs/layers.md) Need more keys than switches? Use layers. +- [RGB](https://github.com/KMKfw/kmk_firmware/tree/master/docs/rgb.md) Light it up +- [ModTap](https://github.com/KMKfw/kmk_firmware/tree/master/docs/modtap.md) Allows mod keys to act as different keys when tapped. + +Common Extentions +- [Power](https://github.com/KMKfw/kmk_firmware/tree/master/docs/power.md) Powersaving features for battery life diff --git a/boards/reviung41/kb.py b/boards/reviung41/kb.py new file mode 100644 index 0000000..9668db1 --- /dev/null +++ b/boards/reviung41/kb.py @@ -0,0 +1,38 @@ +import board + +from kmk.kmk_keyboard import KMKKeyboard as _KMKKeyboard +from kmk.matrix import DiodeOrientation +from kmk.matrix import intify_coordinate as ic + + +class KMKKeyboard(_KMKKeyboard): + col_pins = ( + board.P0_22, + board.P0_24, + board.P1_00, + board.P0_11, + board.P1_04, + board.P1_06, + ) + row_pins = ( + board.P0_31, + board.P0_29, + board.P0_02, + board.P1_15, + board.P1_13, + board.P1_11, + board.P0_10, + ) + diode_orientation = DiodeOrientation.COLUMNS + rgb_pixel_pin = board.P0_06 + rgb_num_pixels = 11 + i2c = board.I2C + powersave_pin = board.P0_13 + + coord_mapping = [] + coord_mapping.extend(ic(0, x) for x in range(12)) + coord_mapping.extend(ic(1, x) for x in range(12)) + coord_mapping.extend(ic(2, x) for x in range(12)) + + # And now, to handle R3, which at this point is down to just five keys + coord_mapping.extend(ic(3, x) for x in range(5)) diff --git a/boards/reviung41/main.py b/boards/reviung41/main.py new file mode 100644 index 0000000..db632d2 --- /dev/null +++ b/boards/reviung41/main.py @@ -0,0 +1,64 @@ +from kb import KMKKeyboard +from kmk.extensions.rgb import RGB +from kmk.keys import KC +from kmk.modules.layers import Layers +from kmk.modules.modtap import ModTap + +keyboard = KMKKeyboard() + +# Adding extentions +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() +layers_ext = Layers() + +keyboard.modules = [layers_ext, modtap] +keyboard.extensions = [rgb] + +# Cleaner key names +_______ = KC.TRNS +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) + +RGB_TOG = KC.RGB_TOG +RGB_HUI = KC.RGB_HUI +RGB_HUD = KC.RGB_HUI +RGB_SAI = KC.RGB_SAI +RGB_SAD = KC.RGB_SAD +RGB_VAI = KC.RGB_VAI +RGB_VAD = KC.RGB_VAD + +keyboard.keymap = [ + [ #QWERTY + KC.TAB, KC.Q, KC.W, KC.E, KC.R, KC.T, KC.Y, KC.U, KC.I, KC.O, KC.P, KC.BSPC, + KC.LCTL, KC.A, KC.S, KC.D, KC.F, KC.G, KC.H, KC.J, KC.K, KC.L, KC.SCLN, KC.QUOT, + KC.LSFT, KC.Z, KC.X, KC.C, KC.V, KC.B, KC.N, KC.M, KC.COMM, KC.DOT, KC.SLSH, RSFT_ENT, + KC.LALT, LOWER, KC.SPC, RAISE, KC.RGUI, + ], + [ #LOWER + KC.ESC, KC.N1, KC.N2, KC.N3, KC.N4, KC.N5, KC.N6, KC.N7, KC.N8, KC.N9, KC.N0, KC.BSPC, + KC.LCTL, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC.LEFT, KC.DOWN, KC.UP, KC.RIGHT, XXXXXXX, XXXXXXX, + KC.LSFT, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, RSFT_SPC, + KC.LALT, LOWER, KC.SPC, RAISE, KC.RGUI, + ], + [ #RAISE + KC.ESC, KC.EXLM, KC.AT, KC.HASH, KC.DLR, KC.PERC, KC.CIRC, KC.AMPR, KC.ASTR, KC.LPRN, KC.RPRN, KC.BSPC, + KC.LCTL, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC.MINS, KC.EQL, KC.LCBR, KC.RCBR, KC.PIPE, KC.GRV, + KC.LSFT, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC.UNDS, KC.PLUS, KC.LBRC, KC.RBRC, KC.BSLS, KC.TILD, + KC.LALT, LOWER, KC.SPC, RAISE, KC.RGUI, + ], + [ #ADJUST + RGB_TOG, RGB_HUI, RGB_SAI, RGB_VAI, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, + XXXXXXX, RGB_HUD, RGB_SAD, RGB_VAD, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, + XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, + KC.LALT, LOWER, KC.SPC, RAISE, KC.RGUI, + ] +] + +if __name__ == '__main__': + keyboard.go() diff --git a/boards/rhymestone/README.md b/boards/rhymestone/README.md new file mode 100644 index 0000000..62b8059 --- /dev/null +++ b/boards/rhymestone/README.md @@ -0,0 +1,19 @@ +# Rhymestone + +![rhymestone](https://boardsource.imgix.net/0968c21e-ed0c-47ec-ae5e-511ec6eb3bd2.jpg?raw=true) + +The Rhymestone is 40-key ortholinear split keyboard. Originally the Rhymestone was created to be sold alongside the Treadstone and used as either a Macro pad or a 10-key numpad, hence the similar naming conventions. However; the Rhymestone is also often used as a standalone split keyboard by people who prefer a 5 column ortholinear layout. + +kb.py is designed to work with the nice!nano + +Retailers (USA) +[Boardsource](https://boardsource.xyz/store/5ecb6aee86879c9a0c22da89) + +Extentions enabled by default +- [Layers](https://github.com/KMKfw/kmk_firmware/tree/master/docs/layers.md) Need more keys than switches? Use layers. +- [BLE_Split](https://github.com/KMKfw/kmk_firmware/tree/master/docs/split.md) Connects halves without wires +- [ModTap](https://github.com/KMKfw/kmk_firmware/tree/master/docs/modtap.md) Allows mod keys to act as different keys when tapped. + +Common Extentions +- [Split](https://github.com/KMKfw/kmk_firmware/tree/master/docs/split.md) Connects halves using a wire +- [Power](https://github.com/KMKfw/kmk_firmware/tree/master/docs/power.md) Powersaving features for battery life diff --git a/boards/rhymestone/kb.py b/boards/rhymestone/kb.py new file mode 100644 index 0000000..249a561 --- /dev/null +++ b/boards/rhymestone/kb.py @@ -0,0 +1,15 @@ +import board + +from kmk.kmk_keyboard import KMKKeyboard as _KMKKeyboard +from kmk.matrix import DiodeOrientation + + +class KMKKeyboard(_KMKKeyboard): + row_pins = (board.P0_31, board.P0_29, board.P0_02, board.P1_15) + col_pins = (board.P0_22, board.P0_24, board.P1_00, board.P0_11, board.P1_04) + diode_orientation = DiodeOrientation.COLUMNS + rgb_pixel_pin = board.P0_06 + rgb_num_pixels = 40 + data_pin = board.P0_08 + i2c = board.I2C + powersave_pin = board.P0_13 diff --git a/boards/rhymestone/main.py b/boards/rhymestone/main.py new file mode 100644 index 0000000..5c4c585 --- /dev/null +++ b/boards/rhymestone/main.py @@ -0,0 +1,51 @@ +from kb import KMKKeyboard +from kmk.extensions.layers import Layers +from kmk.extensions.split import Split, SplitSide, SplitType +from kmk.keys import KC + +keyboard = KMKKeyboard() + +# TODO Comment one of these on each side +split_side = SplitSide.LEFT +split_side = SplitSide.RIGHT +split = Split(split_type=SplitType.BLE, split_side=split_side) + +layers_ext = Layers() + +keyboard.extensions = [layers_ext, split] + +# Cleaner key names +_______ = KC.TRNS +XXXXXXX = KC.NO + +LOWER = KC.MO(2) +RAISE = KC.MO(1) + +KC_Z_SF = KC.LSFT(KC.Z) +KC_SLSF = KC.RSFT(KC.SLSH) +KC_11SF = KC.LSFT(KC.F11) +KC_GRSF = KC.RSFT(KC.GRV) + +keyboard.keymap = [ + [ #QWERTY + KC.Q, KC.W, KC.E, KC.R, KC.T, KC.Y, KC.U, KC.I, KC.O, KC.P, + KC.A, KC.S, KC.D, KC.F, KC.G, KC.H, KC.J, KC.K, KC.L, KC.ENT, + KC.Z_SF, KC.X, KC.C, KC.V, KC.B, KC.N, KC.M, KC.COMM, KC.DOT, KC.SLSF, + KC.LCTL, KC.LALT, KC.LGUI, LOWER, KC.BSPC, KC.SPC, RAISE, KC.RGUI, KC.APP, KC.RCTL + ], + [ #RAISE + KC.N1, KC.N2, KC.N3, KC.N4, KC.N5, KC.N6, KC.N7, KC.N8, KC.N9, KC.N0, + KC.LSFT, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC.LEFT, KC.DOWN, KC.UP, KC.RGHT, KC.RSFT, + XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC.MINS, KC.RO, KC.COMM, KC.DOT, KC.SLSF, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ + ], + [ #LOWER + KC.F1, KC.F2, KC.F3, KC.F4, KC.F5, KC.MINS, KC.EQL, KC.LBRC, KC.RBRC, KC.BSLS, + KC.F6, KC.F7, KC.F8, KC.F9, KC.F10, XXXXXXX, XXXXXXX, XXXXXXX, KC.SCLN, KC.QUOT, + KC.N11SF, KC.F12, KC.ESC, KC.TAB, _______, KC.DEL, XXXXXXX, XXXXXXX, KC.RO, KC.GRSF, + _______, _______, _______, _______, KC.DEL, _______, _______, _______, _______, _______ + ] +] + +if __name__ == '__main__': + keyboard.go() diff --git a/boards/tg4x/README.md b/boards/tg4x/README.md new file mode 100644 index 0000000..aef7d06 --- /dev/null +++ b/boards/tg4x/README.md @@ -0,0 +1,17 @@ +# TG4X + +![TG4X](https://boardsource.imgix.net/d50e1163-06dd-4c18-826e-caacd0a4a33d.jpg?raw=true) + +TG4X is a 45% staggered keyboard, compared to a standard 40% stagger it has one additional column which makes it an approachable and highly use-able 40%-ish stagger. + +kb.py is designed to work with the nice!nano + +Retailers (USA) +[Boardsource](https://boardsource.xyz/store/5eff7ead037395179221b90c) + +Extentions enabled by default +- [Layers](https://github.com/KMKfw/kmk_firmware/tree/master/docs/layers.md) Need more keys than switches? Use layers. +- [RGB](https://github.com/KMKfw/kmk_firmware/tree/master/docs/rgb.md) Light it up + +Common Extentions +- [Power](https://github.com/KMKfw/kmk_firmware/tree/master/docs/power.md) Powersaving features for battery life diff --git a/boards/tg4x/kb.py b/boards/tg4x/kb.py new file mode 100644 index 0000000..96d76ee --- /dev/null +++ b/boards/tg4x/kb.py @@ -0,0 +1,31 @@ +import board + +from kmk.kmk_keyboard import KMKKeyboard as _KMKKeyboard +from kmk.matrix import DiodeOrientation + + +class KMKKeyboard(_KMKKeyboard): + row_pins = ( + board.P1_06, + board.P1_04, + board.P0_11, + board.P1_00, + board.P0_24, + board.P0_22, + board.P0_20, + board.P0_17, + ) + col_pins = [ + board.P0_06, + board.P1_11, + board.P1_13, + board.P1_15, + board.P0_02, + board.P0_29, + board.P0_31, + ] + diode_orientation = DiodeOrientation.COLUMNS + rgb_pixel_pin = board.P0_08 + rgb_num_pixels = 6 + i2c = board.I2C + powersave_pin = board.P0_13 diff --git a/boards/tg4x/main.py b/boards/tg4x/main.py new file mode 100644 index 0000000..4105350 --- /dev/null +++ b/boards/tg4x/main.py @@ -0,0 +1,36 @@ +from kb import KMKKeyboard +from kmk.extensions.rgb import RGB +from kmk.keys import KC +from kmk.modules.layers import Layers + +keyboard = KMKKeyboard() + +# Cleaner key names +_______ = KC.TRNS +XXXXXXX = KC.NO + +# Adding extentions +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) + +layers_ext = Layers() + +keyboard.modules = [layers_ext] +keyboard.extensions = [rgb] + +keyboard.keymap = [ + [ #QWERTY + KC.ESC, KC.Q, KC.W, KC.E, KC.R, KC.T, KC.Y, KC.U, KC.I, KC.O, KC.P, KC.MINS, KC.DEL,\ + KC.TAB, KC.A, KC.S, KC.D, KC.F, KC.G, KC.H, KC.J, KC.K, KC.L, KC.QUOT, KC.ENT,\ + KC.LSFT, KC.Z, KC.X, KC.C, KC.V, KC.B, KC.N, KC.M, KC.COMM, KC.DOT, KC.SLSH, KC.RSFT,\ + KC.LCTL, KC.LGUI, KC.LALT, KC.SPACE, KC.SPACE, KC.RALT, KC.RGUI, KC.RCTL, KC.MO(1)\ + ], + [ #LOWER + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, _______, _______, _______, _______ + ], +] + +if __name__ == '__main__': + keyboard.go() diff --git a/boot.py b/boot.py index dd14a28..aafa105 100755 --- a/boot.py +++ b/boot.py @@ -1,3 +1,3 @@ import supervisor -supervisor.set_next_stack_limit(4096 + 1024) +supervisor.set_next_stack_limit(4096 + 4096) diff --git a/docs/Getting_Started.md b/docs/Getting_Started.md new file mode 100644 index 0000000..f628366 --- /dev/null +++ b/docs/Getting_Started.md @@ -0,0 +1,71 @@ +# Getting Started + + ## Microcontrollers + KMK will run on most microcontrollers supported by + [Circuitpython](https://circuitpython.org/downloads). Our recommended + microcontrollers are found [here](Officially_Supported_Microcontrollers.md) + +## Firmware +### KMKPython +KMKPython is a fork of Circuitpython, but with libraries for most extensions +built in. This saves you from having to get them all and keep them updated +yourself. There may be other features added in the future that are exclusive to +KMKPython. For the nice!nano, this is highly recommended, and used in place of +Circuitpython. +Notable differences include +- Built in libraries for bluetooth, RGB, and more +- Saves space as builds are optimized for keyboards +- Microcontrollers like the nice!nano will be able to access all features out of +the box. + +### Circuitpython +Circuitpython can be installed by following this guide using the guide +[here](https://learn.adafruit.com/welcome-to-circuitpython/installing-circuitpython). +It's recommended to run the latest stable version that is at least 5.0 or higher. +Beta versions may work, but expect limited support. +#### Notable differences include + - Supports more devices + - Less built in libraries. If using RGB, bluetooth, and more, you will have to + add these libraries yourself + - Some devices such as the nice!nano don't have much free space, so not all + features can be installed at the same time + +## Getting KMK +You can always find the latest releases on our CDN, in +[compiled and optimized](https://cdn.kmkfw.io/kmk-latest.zip) and +[raw, hackable text file](https://cdn.kmkfw.io/kmk-latest.unoptimized.zip) +forms. These follow the `master` branch here on GitHub. Just get the KMK folder +and drop this directly in the CIRCUITPYTHON directory (not in a sub folder). +Make sure to extract the zip, and put the `kmk` folder on the root of the +CIRCUITPY drive on the microcontroller + +## Turning a controller into a keyboard +### Supported keyboards +If your keyboard and microcontroller are officially supported, simply visit the +page for your files, and dropping them on the root of the "flash drive". Those +pages can be found [here](https://github.com/KMKfw/boards). You will need the +`kb.py` and `main.py`. More advanced instructions can be found +[here](config_and_keymap.md). If using Curcuitpython and NOT KMKPython, you will +also need [boot.py](https://github.com/KMKfw/kmk_firmware/blob/master/boot.py) + +### Porting a keyboard +If you are porting a board to KMK, check the page [here](porting_to_kmk.md). + +### Handwired Keyboard +If you are doing a hand wire, check [here](handwiring.md) + +## Additional features +Want to have fun features such as RGB, split keyboards and more? Check out what +extensions can do [here](extensions.md) + +## Debugging +Debugging help can be found [here](debugging.md) + +## Additional help and support +If you need support with KMK or just want to say hi, find us in +[#kmkfw:klar.sh on Matrix](https://matrix.to/#/#kmkfw:klar.sh). This channel is +bridged to Discord [here](https://discordapp.com/widget?id=493256121075761173&theme=dark) +for convenience. If you ask for help on chat or open a bug report, if possible +please give us your commit SHA, found by running +`from kmk.consts import KMK_RELEASE; print(KMK_RELEASE)` in the REPL on your +controller. diff --git a/docs/Offiially_Supported_Microcontrollers.md b/docs/Offiially_Supported_Microcontrollers.md new file mode 100644 index 0000000..078a308 --- /dev/null +++ b/docs/Offiially_Supported_Microcontrollers.md @@ -0,0 +1,47 @@ +# Officially supported microcontrollers +While most Circuitpython devices are great for hand wired keyboards, most +keyboards are designed to accept a Pro Micro. The boards listed below either +are, or can be adapted to that pinout to use common keyboards already on the market. + +## Nice!Nano +Features include +- Pro Micro pinout +- Both USB HID and Bluetooth support +- Can do bluetooth split keyboards with no wires at all +- Has battery support including charging + +Downsides +- $25 USD per microcontroller at most retailers + +Recommended Retailers +[Boardsource](https://boardsource.xyz/store/5f4a1733bbaa5c635b83ed67) +[NiceKeyboards](https://nicekeyboards.com/collections/group-buy/products/nice-nano-v1-0). + +## ItsyBitsy M4 Express +Features include +- Affordable at $15 USD +- Can run most features of KMK including RGB + +Downsides +- Needs adapted to work with Pro Micro pinout keyboards. Adapter can be found +[HERE](https://github.com/KMKfw/kmk_firmware/tree/master/hardware) + +Recommended Retailers +[Adafruit](https://www.adafruit.com/product/3800) + +## Adafruit ItsyBitsy nRF52840 Express +Features include +- Both USB HID and Bluetooth support +- More affordable than the Nice!Nano at only $18 + +Downsides +- Needs adapted to work with Pro Micro pinout keyboards. Adapter can be found +[HERE](https://github.com/KMKfw/kmk_firmware/tree/master/hardware) +- No battery support without addon board found +[HERE](https://www.adafruit.com/product/2124) + +## Other microcontrollers +What you'll need to have at minimum +- CircuitPython/KMKpython +- 256KB of flash storage +- HID over USB and/or Bluetooth. diff --git a/docs/ble_hid.md b/docs/ble_hid.md new file mode 100644 index 0000000..94f211e --- /dev/null +++ b/docs/ble_hid.md @@ -0,0 +1,31 @@ +# BLE HID +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). +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. + +## Enabling BLE + +To enable BLE hid, change the keyboard.go(). By default, the advertised name +will be the name of the "flash drive". By default this is CIRCUITPY + +```python +if __name__ == '__main__': + keyboard.go(hid_type=HIDModes.BLE) +``` + +## Changing the advertisee name +There are two ways to change the advertising name. The first would be to +[change the name of the drive](https://learn.adafruit.com/welcome-to-circuitpython/the-circuitpy-drive). +The second would be to change the keyboard.go() like this. + +```python +if __name__ == '__main__': + keyboard.go(hid_type=HIDModes.BLE, ble_name='KMKeyboard') +``` + + diff --git a/docs/config_and_keymap.md b/docs/config_and_keymap.md index 0e0e614..1e2c272 100644 --- a/docs/config_and_keymap.md +++ b/docs/config_and_keymap.md @@ -2,9 +2,10 @@ KMK is configured through a rather large plain-old-Python class called `KMKKeyboard`. Subclasses of this configuration exist which pre-fill defaults -for various known keyboards (for example, many Keebio keyboards are supported -through our ItsyBitsy to ProMicro pinout adapter). This class is the main -interface between end users and the inner workings of KMK. Let's dive in! +for various known keyboards (for example, many QMK, TMK, or ZMK keyboards +are supported with a nice!nano, or through our ItsyBitsy to ProMicro pinout adapter. +This class is the main interface between end users and the inner workings of KMK. +Let's dive in! - Edit or create a file called `main.py` on your `CIRCUITPY` drive. You can also keep this file on your computer (perhaps under `user_keymaps` - please feel @@ -17,9 +18,6 @@ interface between end users and the inner workings of KMK. Let's dive in! corruption bugs, or you might just have bad luck and delete the wrong file some day. -- Import the `KMKKeyboard` object for your keyboard from `kmk.boards` (or, if - handwiring your keyboard, import `KMKKeyboard` from `kmk.kmk_keyboard`). - - Assign a `KMKKeyboard` instance to a variable (ex. `keyboard = KMKKeyboard()` - note the parentheses) @@ -77,29 +75,10 @@ keyboard.keymap = [[KC.A, KC.B]] You can further define a bunch of other stuff: -- `debug_enabled` which will spew a ton of debugging information to the serial +- `keyboard.debug_enabled` which will spew a ton of debugging information to the serial console. This is very rarely needed, but can provide very valuable information if you need to open an issue. -- `unicode_mode` from `kmk.consts.UnicodeMode`, which defines the default - operating system implementation to use for unicode sequences (see examples - below, or `unicode.md`. This can be changed after boot with a key (see - `keycodes.md`) +- `keyboard.tap_time` which defines how long `KC.TT` and `KC.LT` will wait before + considering a key "held" (see `layers.md`) -- `tap_time` which defines how long `KC.TT` and `KC.LT` will wait before - considering a key "held" (see `keycodes.md`) - -- `leader_dictionary`, which defines leader sequences (see `leader.md`), defined - as tuples of keycode objects (or you can use - `kmk.keycodes.generate_leader_dictionary_seq` with a string) - -We also support unicode sequences (emojis, emoticons, umlauted letters, -whatever) if your operating system and system setup do! See `unicode.md` for -details. - -[Here's a giant example of all the -above](https://github.com/KMKfw/kmk_firmware/blob/master/user_keymaps/klardotsh/klarank_featherm4.py). -This is my personal 4x12 matrix layout running on a Planck Rev6 PCB, with a -Feather M4 Express wired up to the outer matrix pins (in somewhat of a "spider" -setup), utilizing most of the above features - it's one of the "kitchen sink -tester" definitions we use on the KMK Core team. diff --git a/docs/debugging.md b/docs/debugging.md index 0b0ba0b..61145ee 100644 --- a/docs/debugging.md +++ b/docs/debugging.md @@ -3,7 +3,7 @@ Debug will output most of the useful state to the console. This can be enable in by setting this in your keymap. NOTE that it will be slower, so only enable this when you need debugging. ```python -DEBUG_ENABLE = True +keyboard.debug_enabled = True ``` The output can be viewed by connecting to the serial port of the keybord. Please refer to [THIS](https://learn.adafruit.com/welcome-to-circuitpython/kattni-connecting-to-the-serial-console) for diff --git a/docs/examples.md b/docs/examples.md deleted file mode 100644 index c8ea87d..0000000 --- a/docs/examples.md +++ /dev/null @@ -1,16 +0,0 @@ -# Examples -Here you can find some examples of what some users have created in their personal keyboard configs. These are here to -help you understand how some of the tools may be used. - -## Changing LED color based on layers -This allows you to create a layer key that also changes colors when pushing a layer key, and restore turn off the lights -when you release the layer key. The example uses the MO though any layer switch keys can be used if imported. Just use the -LAYER_1 key in your keymap, and it's ready to go! You can change animations, colors, or anything in there. - -```python -LAYER_1 = KC.MO(1) -LAYER_1.after_press_handler(lambda *args, **kwargs: keyboard.pixels.set_hsv_fill(100, 100, 100)) -LAYER_1.after_release_handler(lambda *args, **kwargs: keyboard.pixels.set_hsv_fill(0, 0, 0)) - -keyboard.keymap = [ ....... LAYER_1 ....... ] -``` \ No newline at end of file diff --git a/docs/extensions.md b/docs/extensions.md new file mode 100644 index 0000000..b93e4a7 --- /dev/null +++ b/docs/extensions.md @@ -0,0 +1,14 @@ +# Extensions +Extensions add features that change the experience, but not the core features of +the keyboard. They are meant to be easy to add, and create your own. These live in +a sandbox to help prevent any bad code from crashing your keyboard. + +## Core Extensions +These extensions are proveded in all builds and can be enabled. Currently offered +extensions are + +- [International](international.md): Adds international keycodes +- [LED](led.md): Adds backlight support. This is for monocolor backlight, not RGB +- [MediaKeys](media_keys.md): Adds support for media keys such as volume +- [RGB](rgb.md): RGB lighting for underglow. Will work on most matrix RGB as will +be treated the same as underglow. diff --git a/docs/flashing.md b/docs/flashing.md index 9ddb6ec..2086f9c 100644 --- a/docs/flashing.md +++ b/docs/flashing.md @@ -18,7 +18,7 @@ If you get permissions errors here, **don't run make as root or with sudo**. See `Troubleshooting` below. ```sh -make MOUNTPOINT=/media/CIRCUITPY USER_KEYMAP=user_keymaps/nameofyourkeymap.py +make MOUNTPOINT=/media/CIRCUITPY USER_KEYMAP=user_keymaps/nameofyourkeymap.py BOARD=board/nameofyourboard/kb.py ``` # Troubleshooting diff --git a/docs/handwiring.md b/docs/handwiring.md new file mode 100644 index 0000000..36423bc --- /dev/null +++ b/docs/handwiring.md @@ -0,0 +1,6 @@ +# Handwire keyboards +This guide will not talk about the physical wiring. Check out our +[recommended microcontrollers](Offiially_Supported_Microcontrollers.md) and +follow the amazing guide for that[here](https://docs.qmk.fm/#/hand_wire). That +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) diff --git a/docs/hardware.md b/docs/hardware.md deleted file mode 100644 index 799afa2..0000000 --- a/docs/hardware.md +++ /dev/null @@ -1,35 +0,0 @@ -## Supported Devices - -| Board | Chipset | Python Platform | Notes | -| ----- | ------- | --------------- | ----- | -| [Adafruit Feather M4 Express](https://www.adafruit.com/product/3857) | Atmel SAMD51 (Cortex M4F) | CircuitPython | An economical solution for basic USB keyboards | -| [Adafruit ItsyBitsy M4 Express](https://www.adafruit.com/product/3800) | Atmel SAMD51 (Cortex M4F) | CircuitPython | A smaller solution for basic USB keyboards | -| [Adafruit Feather NRF52840 Express](https://www.adafruit.com/product/4062) | Cortex M4F/nrf52840 | CircuitPython | Supports USB HID and soon BLE (Bluetooth) | -| [Seeed nRF52840 Micro Dev Kit](https://www.seeedstudio.com/nRF52840-Micro-Development-Kit-p-3079.html) | M4F/nrf52840 | CircuitPython | Supports USB HID and soon BLE (Bluetooth) | - - -## Support Planned/WIP -| Board | Chipset | Python Platform | Notes | -| ----- | ------- | --------------- | ----- | -| [Planck rev6 Keyboard](https://olkb.com/planck) | STM32F303 | CircuitPython | Requires porting CircuitPython to STM32F3. | -| [Proton C Controller?](https://olkb.com/parts/qmk-proton-c) | STM32F303CCT6 | CircuitPython | Requires porting CircuitPython to STM32F3. | - - - -## Porting new devices -Pull requests are welcome and encouraged to add support for new -keyboards/microcontrollers. The base requirements for device support -- CircuitPython -- 256KB of flash storage -- HID over USB and/or Bluetooth. - -## Secondary Support - -In the future, secondary support for lesser controllers is planned. One of -these cases is the pro micro being used for a slave half of a split keyboard -while all actual work is being done by a supported board. This could also be -used to convert boards that use USB or i2c that run lesser chips to a KMK -board, with a supported board acting as a translation layer. Support for -a converter is planned with the inspiration coming from the [Hasu USB to -USB Controller Converter](https://www.1upkeyboards.com/shop/controllers/usb-to-usb-converter/) -and would allow for conversion to KMK as opposed to TMK or QMK with that board. \ No newline at end of file diff --git a/docs/international.md b/docs/international.md new file mode 100644 index 0000000..d61dac9 --- /dev/null +++ b/docs/international.md @@ -0,0 +1,35 @@ +# International Keycodes +International extention adds keys for non US layouts. It can simply be added to +the extentions list. + +```python +from kmk.extensions.international import International +keyboard.extensions.append(International()) +``` + +## Keycodes + +|Key |Aliases |Description | +|-----------------------|--------------------|-----------------------------------------------| +|`KC.NONUS_HASH` |`KC.NUHS` |Non-US `#` and `~` | +|`KC.NONUS_BSLASH` |`KC.NUBS` |Non-US `\` and | | +|`KC.INT1` |`KC.RO` |JIS `\` and | | +|`KC.INT2` |`KC.KANA` |JIS Katakana/Hiragana | +|`KC.INT3` |`KC.JYEN` |JIS `¥` | +|`KC.INT4` |`KC.HENK` |JIS Henkan | +|`KC.INT5` |`KC.MHEN` |JIS Muhenkan | +|`KC.INT6` | |JIS Numpad `,` | +|`KC.INT7` | |International 7 | +|`KC.INT8` | |International 8 | +|`KC.INT9` | |International 9 | +|`KC.LANG1` |`KC.HAEN` |Hangul/English | +|`KC.LANG2` |`KC.HANJ` |Hanja | +|`KC.LANG3` | |JIS Katakana | +|`KC.LANG4` | |JIS Hiragana | +|`KC.LANG5` | |JIS Zenkaku/Hankaku | +|`KC.LANG6` | |Language 6 | +|`KC.LANG7` | |Language 7 | +|`KC.LANG8` | |Language 8 | +|`KC.LANG9` | |Language 9 | + + diff --git a/docs/keycodes.md b/docs/keycodes.md index 1e7e62e..6d44f30 100644 --- a/docs/keycodes.md +++ b/docs/keycodes.md @@ -52,7 +52,6 @@ |`KC.LBRACKET` |`KC.LBRC` |`[` and `{` | |`KC.RBRACKET` |`KC.RBRC` |`]` and `}` | |`KC.BSLASH` |`KC.BSLS` |`\` and | | -|`KC.NONUS_HASH` |`KC.NUHS` |Non-US `#` and `~` | |`KC.SCOLON` |`KC.SCLN` |`;` and `:` | |`KC.QUOTE` |`KC.QUOT` |`'` and `"` | |`KC.GRAVE` |`KC.GRV`, `KC.ZKHK` |` and `~`, JIS Zenkaku/Hankaku| @@ -102,7 +101,6 @@ |`KC.KP_9` |`KC.P9` |Keypad `9` and Page Up | |`KC.KP_0` |`KC.P0` |Keypad `0` and Insert | |`KC.KP_DOT` |`KC.PDOT` |Keypad `.` and Delete | -|`KC.NONUS_BSLASH` |`KC.NUBS` |Non-US `\` and | | |`KC.KP_EQUAL` |`KC.PEQL` |Keypad `=` | |`KC.F13` | |F13 | |`KC.F14` | |F14 | @@ -121,24 +119,6 @@ |`KC.LOCKING_SCROLL` |`KC.LSCR` |Locking Scroll Lock | |`KC.KP_COMMA` |`KC.PCMM` |Keypad `,` | |`KC.KP_EQUAL_AS400` | |Keypad `=` on AS/400 keyboards | -|`KC.INT1` |`KC.RO` |JIS `\` and | | -|`KC.INT2` |`KC.KANA` |JIS Katakana/Hiragana | -|`KC.INT3` |`KC.JYEN` |JIS `¥` | -|`KC.INT4` |`KC.HENK` |JIS Henkan | -|`KC.INT5` |`KC.MHEN` |JIS Muhenkan | -|`KC.INT6` | |JIS Numpad `,` | -|`KC.INT7` | |International 7 | -|`KC.INT8` | |International 8 | -|`KC.INT9` | |International 9 | -|`KC.LANG1` |`KC.HAEN` |Hangul/English | -|`KC.LANG2` |`KC.HANJ` |Hanja | -|`KC.LANG3` | |JIS Katakana | -|`KC.LANG4` | |JIS Hiragana | -|`KC.LANG5` | |JIS Zenkaku/Hankaku | -|`KC.LANG6` | |Language 6 | -|`KC.LANG7` | |Language 7 | -|`KC.LANG8` | |Language 8 | -|`KC.LANG9` | |Language 9 | |`KC.LCTRL` |`KC.LCTL` |Left Control | |`KC.LSHIFT` |`KC.LSFT` |Left Shift | |`KC.LALT` | |Left Alt | @@ -190,11 +170,10 @@ |Key |Description | |-----------------------|---------------------------------------------------------------------| -|`KC.RESET` |Put the keyboard into DFU mode for flashing | +|`KC.RESET` |Restarts the keyboard | |`KC.DEBUG` |Toggle `debug_enabled`, which enables log spew to serial console | |`KC.GESC` |Escape when tapped, ` when pressed with Shift or GUI| |`KC.BKDL` |Backspace when tapped, Delete when pressed with GUI | -|`KC.LEAD` |The [Leader key] | |`KC.UC_MODE_NOOP` |Sets UnicodeMode to NOOP | |`KC.UC_MODE_LINUX` |Sets UnicodeMode to Linux | |`KC.UC_MODE_MACOS` |Sets UnicodeMode to MocOS | @@ -202,19 +181,6 @@ |`KC.MACRO_SLEEP_MS(ms)`|Sleeps in a macro. Check MACROS for more information. | -## [Layer Switching] - -|Key |Description | -|-----------------|------------------------------------------------------------------------| -|`KC.DF(layer)` |Switches the default layer | -|`KC.MO(layer)` |Momentarily activates layer, switches off when you let go | -|`KC.LM(layer, mod)` |As `MO(layer)` but with `mod` active | -|`KC.LT(layer, kc)` |Momentarily activates layer if held, sends kc if tapped | -|`KC.TG(layer)` |Toggles the layer (enables it if no active, and vise versa) | -|`KC.TO(layer)` |Activates layer and deactivates all other layers | -|`KC.TT(layer)` |Momentarily activates layer if held, toggles it if tapped repeatedly | - - ## [Modifiers] |Key |Description | @@ -230,41 +196,6 @@ |`KC.RALT(kc)`|Hold Right Alt and press `kc` | |`KC.RGUI(kc)`|Hold Right GUI and press `kc` | -## [RGB/Underglow] - -|Key |Aliases |Description | -|-----------------------------|-------------------|----------------------------| -|`KC.RGB_TOG` | |Toggles RGB | -|`KC.RGB_HUI` | |Increase Hue | -|`KC.RGB_HUD` | |Decrease Hue | -|`KC.RGB_SAI` | |Increase Saturation | -|`KC.RGB_SAD` | |Decrease Saturation | -|`KC.RGB_VAI` | |Increase Value | -|`KC.RGB_VAD` | |Decrease Value | -|`KC.RGB_MODE_PLAIN` |`RGB_M_P` |Static RGB | -|`KC.RGB_MODE_BREATHE` |`RGB_M_B` |Breathing animation | -|`KC.RGB_MODE_RAINBOW` |`RGB_M_R` |Rainbow animation | -|`KC.RGB_MODE_BREATHE_RAINBOW`|`RGB_M_BR` |Breathing rainbow animation | -|`KC.RGB_MODE_KNIGHT` |`RGB_M_K` |Knightrider animation | - - -## [Mod-Tap Keys] - -|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| ## [Bluetooth Keys] diff --git a/docs/layers.md b/docs/layers.md new file mode 100644 index 0000000..b34fb9c --- /dev/null +++ b/docs/layers.md @@ -0,0 +1,21 @@ +# Layers +Layers module adds keys for accessing other layers. It can simply be added to + the extentions list. + +```python +from kmk.modules.layers import Layers +keyboard.modules.append(Layers()) +``` + + ## Keycodes + +|Key |Description | +|-----------------|------------------------------------------------------------------------| +|`KC.DF(layer)` |Switches the default layer | +|`KC.MO(layer)` |Momentarily activates layer, switches off when you let go | +|`KC.LM(layer, mod)` |As `MO(layer)` but with `mod` active | +|`KC.LT(layer, kc)` |Momentarily activates layer if held, sends kc if tapped | +|`KC.TG(layer)` |Toggles the layer (enables it if no active, and vise versa) | +|`KC.TO(layer)` |Activates layer and deactivates all other layers | +|`KC.TT(layer)` |Momentarily activates layer if held, toggles it if tapped repeatedly | + diff --git a/docs/leader.md b/docs/leader.md deleted file mode 100644 index be69cee..0000000 --- a/docs/leader.md +++ /dev/null @@ -1,68 +0,0 @@ -# Leader Key -The leader key acts as a prefix to a key sequence. These can be used to trigger macros quickly -without dedicated keys set to each function. For those of you who dislike key combos, such as -Ctrl+Shift+Esc, then this feature is for you. This is very much inspired from vim. - -Leader key sequences can be as long or short as you like. The action must be a macro, so it -can be things like unicode macros, or generic macros. The example below shows how you would -trigger task manager in Windows with a leader sequence. - -1. Assign a key to KC.LEAD -2. Above your keymap, include a LEADER_DICTIONARY. - -```python -from kmk.macros.simple import simple_key_sequence - -# ... - -keyboard.leader_dictionary = { - (KC.T, KC.A, KC.S, KC.K): simple_key_sequence([Modifiers.KC_LCTRL(Modifiers.KC_LSHIFT(Common.KC_ESC))]) -} - -keymap = [...KC.LEAD,...] - -# ... -``` - -If defining tuples of keycodes is too obtuse for you, we have a convenience -function available for that, too! - -```python -from kmk.keycodes import generate_leader_dictionary_seq as glds - -# ... - -keyboard.leader_dictionary = { - glds('task'): simple_key_sequence([Modifiers.KC_LCTRL(Modifiers.KC_LSHIFT(Common.KC_ESC))]) -} - -# ... -``` - -# Modes -1. LeaderMode.TIMEOUT (the default) -2. LeaderMode.ENTER - -### Timeout Mode -Will expire after a timer and trigger the sequence that matches if any. -This can be enabled with -```python -from kmk.consts import LeaderMode -keyboard.leader_mode = LeaderMode.TIMEOUT -``` - -The timeout can be set like this -```python -keyboard.leader_timeout = 2000 # in milliseconds-ish -``` - -The timeout defaults to `1000`, which is roughly a second. - -### Enter Mode -Has no timeout. To end sequence press the enter key, or cancel and do nothing, press escape. -This can be enabled with - -```python -from kmk.consts import LeaderMode -keyboard.leader_mode = LeaderMode.ENTER -``` diff --git a/docs/led.md b/docs/led.md index 1fd495f..2d0b8b0 100644 --- a/docs/led.md +++ b/docs/led.md @@ -1,5 +1,17 @@ # LED (Mono color backlight) Want your keyboard to shine? Add some lights! + +## Enabling the extention +The only required values that you need to give the LED extention would be the +pixel pin, and the number of pixels/LED's. If using a split keyboard, this number +is per side, and not the total of both sides. +```python +from kmk.extensions.RGB import RGB +from kb import led_pin # This can be imported or defined manually + +led_ext = LED(led_pin=led_pin) +keyboard.extensions.append(led_ext) +``` ## [Keycodes] @@ -14,69 +26,16 @@ Want your keyboard to shine? Add some lights! |`KC.LED_MODE_BREATHE` |`LED_M_B` |Breathing animation | ## Configuration -|Define |Default |Description | -|-----------------------------------------|-------------|------------------------------------------------| -|`keyboard.led_config['brightness_step']` |`5` |The number of steps to change the brightness by | -|`keyboard.led_config['brightness_limit']`|`100` |The maximum brightness level in percent | - -## Built-in Animation Configuration -|Define |Default |Description | -|-----------------------------------------|-------------|-------------------------------------------------------------------------------------| -|`keyboard.led_config['breath_center']` |`1.5` |Used to calculate the curve for the breathing animation. Anywhere from 1.0 - 2.7 is valid| - -## Functions - -If you want to create your own animations, or for example, change the lighting in a macro, or a layer switch, here are some functions that are available. - -|Function |Description | -|--------------------------------------------|--------------------------------------------------------------------------------------------| -|`keyboard.pixels.increase_brightness(step)` |Increases hue by a given step | -|`keyboard.pixels.decrease_brightness(step)` |Decreases hue by a given step | -|`keyboard.pixels.set_brightness(percent)` |Increases saturation by a given step | - -## Direct variable access -|Define |Default |Description | -|-----------------------------------|-----------|--------------------------------------------------------------------------------------------------------| -|`keyboard.led.brightness` |`0` |Sets the brightness by percent 0-100 | -|`keyboard.led.brightness_limit` |`100` |Sets the limit of brightness | -|`keyboard.led.brightness_step` |`5` |Sets the step value to change brightness by | -|`keyboard.led.animation_mode` |`static` |This can be changed to any modes included, or to something custom for user animations. Any string is valid | -|`keyboard.led.animation_speed` |`1` |Increases animation speed of most animations. Recommended 1-5, Maximum 10. | - -## User animations -User animations can be created as well. An example of a light show would look like this +All of these values can be set by default for when the keyboard boots. ```python -from kmk.keys import make_key - -def start_flicker(*args, **kwargs): - # Setting mode to user will use the user animation - keyboard.led.animation_mode = 'user' - - -def flicker(self): - # This is the code that is run every cycle that can serve as an animation - # Refer to the kmk/rgb.py for actual examples of what has been done - if self.brightness == 0: - self.brightness = 100 - else: - self.brightness = 0 - keyboard.led.set_brightness(self.brightness) - return self - - -# This is what "gives" your function to KMK so it knows what your animation code is -keyboard.led_config['user_animation'] = flicker - -# Makes a key that would start your animation -LS = make_key(on_press=start_flicker()) - -keymap = [...LS,...] +from kmk.extentions.led import AnimationModes +led_ext = LED( + led_pin=led_pin, + brightness_step=5, + brightness_limit=100, + breathe_center=1.5, + animation_mode=AnimationModes.STATIC, + animation_speed=1, + val=100, + ) ``` - -# Troubleshooting -Make sure that your board supports LED backlight by checking for a line with "LED_PIN". If it does not, you can add it to your keymap. - -|Define |Description | -|---------------------|---------------------------------------------| -|`keyboard.led_pin` |The pin connected to the data pin of the LEDs| - diff --git a/docs/media_keys.md b/docs/media_keys.md new file mode 100644 index 0000000..af9f56e --- /dev/null +++ b/docs/media_keys.md @@ -0,0 +1,23 @@ +# Media Keys +Media keys extention adds keys for common media control keys. It can simply be +added to the extentions list. + +```python +from kmk.extensions.media_keys import MediaKeys +keyboard.extensions.append(MediaKeys()) +``` + + ## Keycodes + +|Key |Aliases |Description | +|-----------------------|--------------------|-----------------------------------------------| +|`KC.AUDIO_MUTE` |`KC.MUTE` |Mute | +|`KC.AUDIO_VOL_UP` |`KC.VOLU` |Volume Up | +|`KC.AUDIO_VOL_DOWN` |`KC.VOLD` |Volume Down | +|`KC.MEDIA_NEXT_TRACK` |`KC.MNXT` |Next Track (Windows) | +|`KC.MEDIA_PREV_TRACK` |`KC.MPRV` |Previous Track (Windows) | +|`KC.MEDIA_STOP` |`KC.MSTP` |Stop Track (Windows) | +|`KC.MEDIA_PLAY_PAUSE` |`KC.MPLY` |Play/Pause Track | +|`KC.MEDIA_EJECT` |`KC.EJCT` |Eject (macOS) | +|`KC.MEDIA_FAST_FORWARD`|`KC.MFFD` |Next Track (macOS) | +|`KC.MEDIA_REWIND` |`KC.MRWD` |Previous Track (macOS) | diff --git a/docs/modtap.md b/docs/modtap.md index 18a5f9a..39d5dee 100644 --- a/docs/modtap.md +++ b/docs/modtap.md @@ -1,10 +1,13 @@ -# ModTap -One key if you tap it, one or more modifier keys if you hold it! - - -## Helpful examples -Just copy the example from New Keycode above your keymap and change KC.SOMETHING to the key that you want when tapped. -After that, just use the new keycode anywhere in your keymap. +# 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.modtap import ModTap +keyboard.modules.append(ModTap()) +``` + +## Keycodes |New Keycode | Description | |-------------------------------------------------------|-----------------------------------------------------------------| @@ -22,9 +25,4 @@ After that, just use the new keycode anywhere in your keymap. |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| -```python -SHFT_HOME = KC.MT(KC.HOME, KC.LSFT) - -keyboard.keymap = [[ ...., SHFT_HOME, ....], ....] -``` diff --git a/docs/modules.md b/docs/modules.md new file mode 100644 index 0000000..4a8e02b --- /dev/null +++ b/docs/modules.md @@ -0,0 +1,15 @@ +# Modules +Modules, unlike extensions, change how your keyboard works. These are meant to have +the ability to alter the core code in any way. Unlike extensions, these are not in a +sandbox, and can make massive changes to normal operation. + +## Core Modules +These modules are proveded in all builds and can be enabled. Currently offered +modules are + +- [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. +- [Power](power.md): Power saving features. This is mostly useful when on battery power. +- [Split](split_keyboards.md): Keyboards split in two. Seems ergonomic! diff --git a/docs/porting_to_kmk.md b/docs/porting_to_kmk.md new file mode 100644 index 0000000..fedf675 --- /dev/null +++ b/docs/porting_to_kmk.md @@ -0,0 +1,71 @@ +# Porting to KMK +Porting a board to KMK is quite simple, and follows this base format. + +```python +import board + +from kmk.kmk_keyboard import KMKKeyboard as _KMKKeyboard +from kmk.matrix import DiodeOrientation +{EXTENTIONS_IMPORT} + +class KMKKeyboard(_KMKKeyboard): +{REQUIRED} + extensions = [] + +``` + +## REQUIRED +This is designed to be replaced with the defining pins of your keyboard. Rows, +colums and the diode direction (if any), should be defined like this +```python + row_pins = [board.p0_31, board.p0_29, board.p0_02, board.p1_15] + col_pins = [board.p0_22, board.p0_24, board.p1_00, board.p0_11, board.p1_04] + diode_orientation = DiodeOrientation.COLUMNS +``` + +## Additional pins for extentions +KMK includes built in extentions for RGB and split keyboards, and powersave. If +these are applicible on your keyboard/microcontroller, the pins should be added +here. Refer to the instructions on the respective extentions page on how to add +them. If not adding any extentions, leave this as an empty list as shown. + +# Coord mapping +If your keyboard is not built electrically as a square (though most are), you can +provide a mapping directly. An example of this is the +[Corne](https://github.com/foostan/crkbd). That has 12 colums for 3 rows, and 6 +colums for the bottom row. Split keyboards count as the total keyboard, not per +side. That would look like this +```python +from kmk.matrix import intify_coordinate as ic + + coord_mapping = [] + coord_mapping.extend(ic(0, x) for x in range(12)) + coord_mapping.extend(ic(1, x) for x in range(12)) + coord_mapping.extend(ic(2, x) for x in range(12)) + # And now, to handle R3, which at this point is down to just six keys + coord_mapping.extend(ic(3, x) for x in range(3, 9)) +``` + + +## Keymaps +Keymaps are organized as a list of lists. Keycodes are added for every key on +each layer. See [keycodes](keycodes.md) for more details on what keycodes are +avaliable. If using layers or other extentions, also refer to the extentions +page for additional keycodes. +```python +from kb import KMKKeyboard +from kmk.keys import KC + +keyboard = KMKKeyboard() + +keyboard.keymap = [ + [KC.A, KC.B], + [KC.C, KC.D], +] + +if __name__ == '__main__': + keyboard.go() +``` + +## More information +More information on keymaps can be found [here](config_and_keymap.md) diff --git a/docs/power.md b/docs/power.md new file mode 100644 index 0000000..9df0e05 --- /dev/null +++ b/docs/power.md @@ -0,0 +1,42 @@ +# Power(save) +This module allows you to save power and is targeted to bluetooth/battery +based keyboards. + +## Keycodes +|Key |Description | +|-----------------------|-------------------------| +|`KC.PS_TOG ` |Toggles powersave on/off | +|`KC.PS_ON ` |Turns powersave on | +|`KC.PS_OFF ` |Turns powersave off | + +# Enabling the extention +To turn on basic power saving, this is all that is required. +```python +from kmk.modules.power import Power + +power = Power() + +keyboard.modules.append(power) + +``` + +## Optional extra power saving +On supported boards, such as the nice!nano, power can be cut on VCC saving extra +power if OLEDS or RGBs are installed. These drain power even when off, so this +will prevent them from doing so. + +```python +from kmk.modules.power import Power + +# Your kb.py may already have this set. If not, add it like this +# import board +# keyboard.powersave_pin = board.P0_13 +power = Power(powersave_pin=keyboard.powersave_pin) + +keyboard.modules.append(power) + +``` + +Make sure that the pin is correct for your microcontroller. The example is for +the nice!nano. Not all microcontrollers have this feature and this can be omitted +if not and there will simply be less power saving. diff --git a/docs/rgb.md b/docs/rgb.md index f21b4c8..b0b508a 100644 --- a/docs/rgb.md +++ b/docs/rgb.md @@ -1,16 +1,18 @@ # RGB/Underglow/Neopixel Want your keyboard to shine? Add some lights! -This does require the neopixel library from Adafruit. This can be downloaded [here](https://github.com/adafruit/Adafruit_CircuitPython_NeoPixel/blob/6e35cd2b40575a20e2904b096508325cef4a71d3/neopixel.py). -It is part of the [Adafruit CircuitPython Bundle](https://github.com/adafruit/Adafruit_CircuitPython_Bundle). +## Circuitpython +If not running KMKpython, this does require the neopixel library from Adafruit. +This can be downloaded +[here](https://github.com/adafruit/Adafruit_CircuitPython_NeoPixel/blob/6e35cd2b40575a20e2904b096508325cef4a71d3/neopixel.py). +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. Currently we support the following addressable LEDs: * WS2811, WS2812, WS2812B, WS2812C, etc. * SK6812, SK6812MINI, SK6805 - * All neopixels - + ### Color Selection KMK uses [Hue, Saturation, and Value](https://en.wikipedia.org/wiki/HSL_and_HSV) to select colors rather than RGB. The color wheel below demonstrates how this works. @@ -19,6 +21,16 @@ Changing the **Hue** cycles around the circle. Changing the **Saturation** moves between the inner and outer sections of the wheel, affecting the intensity of the color. Changing the **Value** sets the overall brightness. +## Enabling the extention +The only required values that you need to give the RGB extention would be the pixel pin, and the number of pixels/LED's. If using a split keyboard, this number is per side, and not the total of both sides. +```python +from kmk.extensions.RGB import RGB +from kb import rgb_pixel_pin # This can be imported or defined manually + +rgb_ext = RGB(pixel_pin=rgb_pixel_pin, num_pixels=27) +keyboard.extensions.append(rgb_ext) +``` + ## [Keycodes] |Key |Aliases |Description | @@ -92,55 +104,46 @@ If you want to create your own animations, or for example, change the lighting i |`keyboard.pixels.animation_mode` |`static` |This can be changed to any modes included, or to something custom for user animations. Any string is valid | |`keyboard.pixels.animation_speed` |`1` |Increases animation speed of most animations. Recommended 1-5, Maximum 10. | +```python +from kmk.extentions.rgb import AnimationModes +rgb_ext = RGB(pixel_pin=rgb_pixel_pin, + num_pixels=27 + num_pixels=0, + val_limit=100, + hue_default=0, + sat_default=100, + rgb_order=(1, 0, 2), # GRB WS2812 + val_default=100, + hue_step=5, + sat_step=5, + val_step=5, + animation_speed=1, + breathe_center=1, # 1.0-2.7 + knight_effect_length=3, + animation_mode=AnimationModes.STATIC, + reverse_animation=False, + ) +``` ## Hardware Modification -To add RGB LED's to boards that don't support them directly, you will have to add a 3 wires. The power wire will run on 3.3v or 5v (depending on the LED), -ground, and data pins will need added to an unused pin on your microcontroller unless your keyboard has specific solder points for them. With those 3 wires -connected, set the pixel_pin as described above, and you are ready to use your RGB LED's/Neopixels. - -## ADVANCED USAGE -If you wish to interact with these as you would normal LED's and do not want help from KMK, you can disable all helper functions from working and access the -neopixel object directly like this. -```python -keyboard.pixels.disable_auto_write = True -keyboard.pixels.neopixel() # <-- This is the neopixel object -``` - -## User animations -User animations can be created as well. An example of a light show would look like this -```python -from kmk.keys import make_key - -def start_light_show(*args, **kwargs): - # Setting mode to user will use the user animation - keyboard.pixels.animation_mode = 'user' - - -def light_show(self): - # This is the code that is run every cycle that can serve as an animation - # Refer to the kmk/rgb.py for actual examples of what has been done - self.hue = (self.hue + 35) % 360 - keyboard.pixels.set_hsv_fill(self.hue, self.sat, self.val) - return self - - -# This is what "gives" your function to KMK so it knows what your animation code is -keyboard.rgb_config['user_animation'] = light_show - -# Makes a key that would start your animation -LS = make_key(on_press=start_light_show) - -keymap = [...LS,...] -``` +To add RGB LED's to boards that don't support them directly, you will have to +add a 3 wires. The power wire will run on 3.3v or 5v (depending on the LED), +ground, and data pins will need added to an unused pin on your microcontroller +unless your keyboard has specific solder points for them. With those 3 wires +connected, set the `pixel_pin` as described above, and you are ready to use your +RGB LED's/Neopixels. ## Troubleshooting ### Incorrect colors If your colors are incorrect, check the pixel order of your specific LED's. Here are some common ones. * WS2811, WS2812, WS2812B, WS2812C are all GRB (1, 0, 2) * SK6812, SK6812MINI, SK6805 are all GRB (1, 0, 2) - * Neopixels will vary depending on which one you buy. It will be listed on the product page.# Troubleshooting - + * Neopixels will vary depending on which one you buy. It will be listed on the product page. + ### Lights don't turn on -Make sure that your board supports LED backlight by checking for a line with "PIXEL_PIN". If it does not, you can add it to your keymap. -If you added the LED's yourself, you will also need to set num_pixels to the number of installed LED's in total. + +Make sure that your board supports LED backlight by checking for a line with +`PIXEL_PIN`. If it does not, you can add it to your keymap. If you added the +LED's yourself, you will also need to set `num_pixels` to the number of +installed LED's in total. diff --git a/docs/sequences.md b/docs/sequences.md index 8c4b08c..f021c87 100644 --- a/docs/sequences.md +++ b/docs/sequences.md @@ -70,35 +70,6 @@ keymap = [...emoticons.BEER, emoticons.HAND_WAVE...] > `kmk.types.AttrDict`, which you can think of as a read-only view over a > dictionary adding attribute-based (dot-notation) access. -Remember from the Leader Mode documentation that leader sequences simply bind to -keys, so extrapolating this example out a bit, you can bind emojis to leader -sequences matching some name or mnemonic representing the sequence you're -looking to send. If you ever wanted to type `fire` and see a fire emoji -on your screen, welcome home. - -```python -from kmk.handlers.sequences import compile_unicode_string_sequences as cuss - -emoticons = cuss({ - # Emojis - 'BEER': r'🍺', - 'BEER_TOAST': r'🍻', - 'FACE_THINKING': r'🤔', - 'FIRE': r'🔥', - 'FLAG_CA': r'🇨🇦', - 'FLAG_US': r'🇺🇸', -}) - -keyboard.leader_dictionary = { - 'beer': emoticons.BEER, - 'beers': emoticons.BEER_TOAST, - 'fire': emoticons.FIRE, - 'uhh': emoticons.FACE_THINKING, - 'fca': emoticons.FLAG_CA, - 'fus': emoticons.FLAG_US, -} -``` - Finally, if you need to send arbitrary unicode codepoints in raw form, that's supported too, through `unicode_codepoint_sequence`. diff --git a/docs/split_keyboards.md b/docs/split_keyboards.md index de9bea9..d8eeedf 100644 --- a/docs/split_keyboards.md +++ b/docs/split_keyboards.md @@ -1,35 +1,63 @@ # Split Keyboards -Split keyboards are mostly the same as unsplit and very easy to adapt a keymap for. Currently -UART is supported, though other modes will come later such as Bluetooth and i2c. +Split keyboards are mostly the same as unsplit. Wired UART and Bluetooth are supported. -## UART -To enable uart it's as simple as adding this line, of course changing the pin +## Wired UART +Wired connections can use UART over 1 or 2 wires. With 2 wires, you will be able +to syncronize the halves allowing additional features in some extentions. ```python -keyboard.split_type = "UART" -keyboard.uart_pin = board.SCL +from kb import data_pin +:from kmk.modules.split import Split, SplitType + +split = Split(split_side=SplitSide.LEFT) +keyboard.modules.append(split) ``` -## Config +## Bluetooth split (aka no TRRS) +Wireless splits are fully featured with 2 way communication allowing all extentions to work 100%. +```python +from kb import data_pin +from kmk.modules.split import Split, SplitType, Split_Side + + +split = Split(split_type=Split.BLE, split_side=SplitSide.LEFT) +OR +split = Split(split_type=Split.BLE, split_side=SplitSide.LEFT) +keyboard.modules.append(split) +``` + +### Config Useful config options: ```python -keyboard.split_flip = True # If your boards are identical but one is flipped, this option is for you -keyboard.split_offsets = [6, 6, 6, 6] # This is the how many keys are on each column on the "target" half +split = Split( + split_flip=True, # If both halves are the same, but flipped, set this True + split_side=None, # Sets if this is to SplitSide.LEFT or SplitSide.RIGHT, or use EE hands + split_type=SplitType.UART, # Defaults to UART + split_target_left=True, # If you want the right to be the target, change this to false + uart_interval=20, # Sets the uarts delay. Lower numbers draw more power + data_pin=None, # The primary data pin to talk to the secondary device with + data_pin2=None, # Second uart pin to allow 2 way communication + target_left=True, # Assumes that left will be the one on USB. Set to folse if it will be the right + uart_flip=True, # Reverses the RX and TX pins if both are provided +) + ``` ### EE HANDS -If you want to plug in on either side, it can be done fairly easily but requires setup. +If you want to plug USB in on either side, or are using bluetooth, this is for +you. -On each half of your keyboard make a file called kmk_side.py and add one of these lines to the file -depending on where each piece is physically located. +Rename your CIRCUITPY drive to something different. The left side must +end in L, the right must is in R. The name must be 11 characters or less! This is +a limitation of the filesystem. You will receive an error if you choose a name +longer than 11 characters. Instructions on how to do that are +[here](https://learn.adafruit.com/welcome-to-circuitpython/the-circuitpy-drive). +For example on NYQUISTL for left and NYQUISTR for the right. + +For wired connections you don't need to pass anything. For bluetooth, remove the `split_side` like this ```python -split_target = "Left" -OR -split_target = "Right" +# Wired +split = Split() +# Wireless +split = Split(split_type=Split.BLE) ``` - -and then in your keymap, add the line -```python -from kmk_side import split_target -``` - diff --git a/docs/support.md b/docs/support.md index 884207e..b0d7503 100644 --- a/docs/support.md +++ b/docs/support.md @@ -1,13 +1,15 @@ # Support -If you are having any issues in installing, configuring, or otherwise issues -with KMK, please reach out to us and our community here. - If you need support with KMK or just want to say hi, find us in [#kmkfw:klar.sh on Matrix](https://matrix.to/#/#kmkfw:klar.sh). This channel is bridged to Discord [here](https://discordapp.com/widget?id=493256121075761173&theme=dark) for convenience. If you ask for help on chat or open a bug report, if possible please give us -your commit SHA, found by running `from kmk.consts import KMK_RELEASE; -print(KMK_RELEASE)` in the REPL on your controller. +your commit SHA, found by running + +```python +from kmk.consts import KMK_RELEASE; print(KMK_RELEASE) +``` + +in the REPL on your controller. diff --git a/docs/tapdance.md b/docs/tapdance.md index 02b82fc..73ccd21 100644 --- a/docs/tapdance.md +++ b/docs/tapdance.md @@ -15,7 +15,7 @@ quickly, then tapped and held (both actions within the timeout window), the letter "b" will be held down until the tap dance key is released. To use this, you may want to define a `tap_time` value in your keyboard -configuration. This is an integer in milliseconds, and defaults to `300`. +configuration. This is an integer in milliseconds, and defaults to `300`. You'll then want to create a sequence of keys using `KC.TD(KC.SOMETHING, KC.SOMETHING_ELSE, MAYBE_THIS_IS_A_MACRO, WHATEVER_YO)`, and place it in your @@ -32,15 +32,9 @@ are planned to be worked around "eventually", but for now are noteworthy: we strongly recommend avoiding `KC.MO` (or any other layer switch keys that use momentary switch behavior - `KC.LM`, `KC.LT`, and `KC.TT`) -- Super fancy stuff like sending a keypress only when the leader key is released - (perhaps based on how long the leader key was held) is **unsupported** - an - example use case might be "tap for Home, hold for Shift" - Here's an example of all this in action: ```python -# user_keymaps/some_silly_example.py -from kmk.boards.klarank import KMKKeyboard from kmk.keycodes import KC from kmk.macros.simple import send_string diff --git a/kmk/ble.py b/kmk/ble.py deleted file mode 100644 index fcbd19b..0000000 --- a/kmk/ble.py +++ /dev/null @@ -1,102 +0,0 @@ -from adafruit_ble import BLERadio -from adafruit_ble.advertising.standard import ProvideServicesAdvertisement -from adafruit_ble.services.standard.hid import HIDService - -from kmk.hid import AbstractHID - -BLE_APPEARANCE_HID_KEYBOARD = 961 -# Hardcoded in CPy -MAX_CONNECTIONS = 2 - - -class BLEHID(AbstractHID): - def post_init(self, ble_name='KMK Keyboard', **kwargs): - self.conn_id = -1 - - self.ble = BLERadio() - self.ble.name = ble_name - self.hid = HIDService() - self.hid.protocol_mode = 0 # Boot protocol - - # Security-wise this is not right. While you're away someone turns - # on your keyboard and they can pair with it nice and clean and then - # listen to keystrokes. - # On the other hand we don't have LESC so it's like shouting your - # keystrokes in the air - if not self.ble.connected or not self.hid.devices: - self.start_advertising() - - self.conn_id = 0 - - @property - def devices(self): - '''Search through the provided list of devices to find the ones with the - send_report attribute.''' - if not self.ble.connected: - return [] - - result = [] - # Security issue: - # This introduces a race condition. Let's say you have 2 active - # connections: Alice and Bob - Alice is connection 1 and Bob 2. - # Now Chuck who has already paired with the device in the past - # (this assumption is needed only in the case of LESC) - # wants to gather the keystrokes you send to Alice. You have - # selected right now to talk to Alice (1) and you're typing a secret. - # If Chuck kicks Alice off and is quick enough to connect to you, - # which means quicker than the running interval of this function, - # he'll be earlier in the `self.hid.devices` so will take over the - # selected 1 position in the resulted array. - # If no LESC is in place, Chuck can sniff the keystrokes anyway - for device in self.hid.devices: - if hasattr(device, 'send_report'): - result.append(device) - - return result - - def _check_connection(self): - devices = self.devices - if not devices: - return False - - if self.conn_id >= len(devices): - self.conn_id = len(devices) - 1 - - if self.conn_id < 0: - return False - - if not devices[self.conn_id]: - return False - - return True - - def hid_send(self, evt): - if not self._check_connection(): - return - - device = self.devices[self.conn_id] - - while len(evt) < len(device._characteristic.value) + 1: - evt.append(0) - - return device.send_report(evt[1:]) - - def clear_bonds(self): - import _bleio - - _bleio.adapter.erase_bonding() - - def next_connection(self): - self.conn_id = (self.conn_id + 1) % len(self.devices) - - def previous_connection(self): - self.conn_id = (self.conn_id - 1) % len(self.devices) - - def start_advertising(self): - advertisement = ProvideServicesAdvertisement(self.hid) - advertisement.appearance = BLE_APPEARANCE_HID_KEYBOARD - - self.ble.start_advertising(advertisement) - - def stop_advertising(self): - self.ble.stop_advertising() diff --git a/kmk/boards/converter/fourtypercentclub/__init__.py b/kmk/boards/converter/fourtypercentclub/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/kmk/boards/converter/keebio/__init__.py b/kmk/boards/converter/keebio/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/kmk/boards/converter/keebio/bdn9.py b/kmk/boards/converter/keebio/bdn9.py deleted file mode 100644 index de7789c..0000000 --- a/kmk/boards/converter/keebio/bdn9.py +++ /dev/null @@ -1,20 +0,0 @@ -import board - -from kmk.kmk_keyboard import KMKKeyboard as _KMKKeyboard -from kmk.matrix import DiodeOrientation - - -class KMKKeyboard(_KMKKeyboard): - col_pins = ( - board.RX, - board.D13, - board.A0, - board.D11, - board.A4, - board.A5, - board.D10, - board.D9, - board.SCK, - ) - diode_orientation = DiodeOrientation.COLUMNS - rgb_pixel_pin = board.TX diff --git a/kmk/boards/converter/keebio/fourier.py b/kmk/boards/converter/keebio/fourier.py deleted file mode 100644 index b32847b..0000000 --- a/kmk/boards/converter/keebio/fourier.py +++ /dev/null @@ -1,15 +0,0 @@ -import board - -from kmk.kmk_keyboard import KMKKeyboard as _KMKKeyboard -from kmk.matrix import DiodeOrientation - - -class KMKKeyboard(_KMKKeyboard): - col_pins = (board.A1, board.A2, board.A3, board.A4, board.A5, board.SCK, board.MOSI) - row_pins = (board.A0, board.D11, board.D10, board.D9) - diode_orientation = DiodeOrientation.COLUMNS - rgb_pixel_pin = board.TX - uart_pin = board.SCL - split_type = 'UART' - split_flip = True - split_offsets = [7, 7, 7, 7] diff --git a/kmk/boards/converter/keebio/iris_r1.py b/kmk/boards/converter/keebio/iris_r1.py deleted file mode 100644 index 4e47e2f..0000000 --- a/kmk/boards/converter/keebio/iris_r1.py +++ /dev/null @@ -1,15 +0,0 @@ -import board - -from kmk.kmk_keyboard import KMKKeyboard as _KMKKeyboard -from kmk.matrix import DiodeOrientation - - -class KMKKeyboard(_KMKKeyboard): - col_pins = (board.A2, board.A3, board.A4, board.A5, board.SCK, board.MOSI) - row_pins = (board.D11, board.D10, board.D9, board.D7, board.D13) - diode_orientation = DiodeOrientation.COLUMNS - rgb_pixel_pin = board.TX - uart_pin = board.SCL - split_type = 'UART' - split_flip = True - split_offsets = [6, 6, 6, 6, 6] diff --git a/kmk/boards/converter/keebio/lapace.py b/kmk/boards/converter/keebio/lapace.py deleted file mode 100644 index 6ff410c..0000000 --- a/kmk/boards/converter/keebio/lapace.py +++ /dev/null @@ -1,28 +0,0 @@ -import board - -from kmk.kmk_keyboard import KMKKeyboard as _KMKKeyboard -from kmk.matrix import DiodeOrientation - - -class KMKKeyboard(_KMKKeyboard): - col_pins = ( - board.SDA, - board.A2, - board.A3, - board.A4, - board.A5, - board.SCK, - board.MOSI, - ) - row_pins = ( - board.TX, - board.A0, - board.RX, - board.A1, - board.D11, - board.D9, - board.D12, - board.D10, - ) - diode_orientation = DiodeOrientation.COLUMNS - rgb_pixel_pin = board.D13 diff --git a/kmk/boards/converter/keebio/levinson_r1.py b/kmk/boards/converter/keebio/levinson_r1.py deleted file mode 100644 index a074d29..0000000 --- a/kmk/boards/converter/keebio/levinson_r1.py +++ /dev/null @@ -1,15 +0,0 @@ -import board - -from kmk.kmk_keyboard import KMKKeyboard as _KMKKeyboard -from kmk.matrix import DiodeOrientation - - -class KMKKeyboard(_KMKKeyboard): - col_pins = (board.A2, board.A3, board.A4, board.A5, board.SCK, board.A0) - row_pins = (board.D11, board.D10, board.D9, board.D7) - diode_orientation = DiodeOrientation.COLUMNS - rgb_pixel_pin = board.TX - uart_pin = board.SCL - split_type = 'UART' - split_flip = True - split_offsets = [6, 6, 6, 6] diff --git a/kmk/boards/converter/keebio/nyquist_r1.py b/kmk/boards/converter/keebio/nyquist_r1.py deleted file mode 100644 index ded8feb..0000000 --- a/kmk/boards/converter/keebio/nyquist_r1.py +++ /dev/null @@ -1,15 +0,0 @@ -import board - -from kmk.kmk_keyboard import KMKKeyboard as _KMKKeyboard -from kmk.matrix import DiodeOrientation - - -class KMKKeyboard(_KMKKeyboard): - col_pins = (board.A2, board.A3, board.A4, board.A5, board.SCK, board.MOSI) - row_pins = (board.D13, board.D11, board.D10, board.D9, board.D7) - diode_orientation = DiodeOrientation.COLUMNS - rgb_pixel_pin = board.TX - uart_pin = board.SCL - split_type = 'UART' - split_flip = True - split_offsets = [6, 6, 6, 6, 6] diff --git a/kmk/boards/converter/keebio/quefrency.py b/kmk/boards/converter/keebio/quefrency.py deleted file mode 100644 index 93e101a..0000000 --- a/kmk/boards/converter/keebio/quefrency.py +++ /dev/null @@ -1,25 +0,0 @@ -import board - -from kmk.kmk_keyboard import KMKKeyboard as _KMKKeyboard -from kmk.matrix import DiodeOrientation - - -class KMKKeyboard(_KMKKeyboard): - # Will need additional work and testing - col_pins = ( - board.A1, - board.A2, - board.A3, - board.A4, - board.A5, - board.SCK, - board.MOSI, - board.D12, - ) - row_pins = (board.A0, board.D13, board.D11, board.D10, board.D9, board.D7) - diode_orientation = DiodeOrientation.COLUMNS - rgb_pixel_pin = board.TX - uart_pin = board.SCL - split_type = 'UART' - split_flip = False - split_offsets = [8, 8, 8, 8, 8, 8] diff --git a/kmk/boards/converter/keebio/rorschach.py b/kmk/boards/converter/keebio/rorschach.py deleted file mode 100644 index fd45d16..0000000 --- a/kmk/boards/converter/keebio/rorschach.py +++ /dev/null @@ -1,15 +0,0 @@ -import board - -from kmk.kmk_keyboard import KMKKeyboard as _KMKKeyboard -from kmk.matrix import DiodeOrientation - - -class KMKKeyboard(_KMKKeyboard): - col_pins = (board.A2, board.A3, board.A4, board.A5, board.SCK, board.MOSI) - row_pins = (board.D11, board.D10, board.D9, board.RX, board.D13) - diode_orientation = DiodeOrientation.COLUMNS - rgb_pixel_pin = board.TX - uart_pin = board.SCL - split_type = 'UART' - split_flip = True - split_offsets = [6, 6, 6, 6, 6] diff --git a/kmk/boards/converter/keebio/tragicforce68.py b/kmk/boards/converter/keebio/tragicforce68.py deleted file mode 100644 index 716b780..0000000 --- a/kmk/boards/converter/keebio/tragicforce68.py +++ /dev/null @@ -1,29 +0,0 @@ -import board - -from kmk.kmk_keyboard import KMKKeyboard as _KMKKeyboard -from kmk.matrix import DiodeOrientation - - -class KMKKeyboard(_KMKKeyboard): - col_pins = ( - board.A0, - board.A1, - board.A2, - board.A3, - board.A4, - board.A5, - board.SCK, - board.MOSI, - ) - row_pins = ( - board.TX, - board.RX, - board.SDA, - board.SCL, - board.D9, - board.D10, - board.D12, - board.D11, - board.D13, - ) - diode_orientation = DiodeOrientation.COLUMNS diff --git a/kmk/boards/converter/keebio/viterbi_r1.py b/kmk/boards/converter/keebio/viterbi_r1.py deleted file mode 100644 index 43ffaa3..0000000 --- a/kmk/boards/converter/keebio/viterbi_r1.py +++ /dev/null @@ -1,15 +0,0 @@ -import board - -from kmk.kmk_keyboard import KMKKeyboard as _KMKKeyboard -from kmk.matrix import DiodeOrientation - - -class KMKKeyboard(_KMKKeyboard): - col_pins = (board.A1, board.A2, board.A3, board.A4, board.A5, board.SCK, board.MOSI) - row_pins = (board.D13, board.D11, board.D10, board.D9, board.D7) - diode_orientation = DiodeOrientation.COLUMNS - rgb_pixel_pin = board.TX - uart_pin = board.SCL - split_type = 'UART' - split_flip = True - split_offsets = [7, 7, 7, 7, 7] diff --git a/kmk/boards/converter/keebio/viterbi_r2.py b/kmk/boards/converter/keebio/viterbi_r2.py deleted file mode 100644 index a17344d..0000000 --- a/kmk/boards/converter/keebio/viterbi_r2.py +++ /dev/null @@ -1,15 +0,0 @@ -import board - -from kmk.kmk_keyboard import KMKKeyboard as _KMKKeyboard -from kmk.matrix import DiodeOrientation - - -class KMKKeyboard(_KMKKeyboard): - col_pins = (board.A0, board.A1, board.A2, board.A3, board.A4, board.A5, board.SCK) - row_pins = (board.D13, board.D11, board.D10, board.D9, board.D7) - diode_orientation = DiodeOrientation.COLUMNS - rgb_pixel_pin = board.TX - uart_pin = board.SCL - split_type = 'UART' - split_flip = True - split_offsets = [7, 7, 7, 7, 7] diff --git a/kmk/boards/converter/lets-split/__init__.py b/kmk/boards/converter/lets-split/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/kmk/boards/converter/lets-split/lets-split_r1.py b/kmk/boards/converter/lets-split/lets-split_r1.py deleted file mode 100644 index 8ddc827..0000000 --- a/kmk/boards/converter/lets-split/lets-split_r1.py +++ /dev/null @@ -1,15 +0,0 @@ -import board - -from kmk.kmk_keyboard import KMKKeyboard as _KMKKeyboard -from kmk.matrix import DiodeOrientation - - -class KMKKeyboard(_KMKKeyboard): - col_pins = (board.A5, board.A4, board.A3, board.A2, board.A1, board.A0) - row_pins = (board.D7, board.D9, board.D10, board.D11) - diode_orientation = DiodeOrientation.COLUMNS - rgb_pixel_pin = board.TX - uart_pin = board.SCL - split_type = 'UART' - split_flip = True - split_offsets = [6, 6, 6, 6] diff --git a/kmk/boards/converter/lets-split/lets-split_r2.py b/kmk/boards/converter/lets-split/lets-split_r2.py deleted file mode 100644 index f13ec94..0000000 --- a/kmk/boards/converter/lets-split/lets-split_r2.py +++ /dev/null @@ -1,15 +0,0 @@ -import board - -from kmk.kmk_keyboard import KMKKeyboard as _KMKKeyboard -from kmk.matrix import DiodeOrientation - - -class KMKKeyboard(_KMKKeyboard): - col_pins = (board.MOSI, board.SCK, board.A5, board.A4, board.A3, board.A2) - row_pins = (board.D11, board.D10, board.D9, board.D7) - diode_orientation = DiodeOrientation.COLUMNS - rgb_pixel_pin = board.TX - uart_pin = board.SCL - split_type = 'UART' - split_flip = True - split_offsets = [6, 6, 6, 6] diff --git a/kmk/consts.py b/kmk/consts.py index 48b3a81..b222ede 100644 --- a/kmk/consts.py +++ b/kmk/consts.py @@ -1,3 +1,5 @@ +from micropython import const + try: from kmk.release_info import KMK_RELEASE except Exception: @@ -5,7 +7,7 @@ except Exception: class UnicodeMode: - NOOP = 0 - LINUX = IBUS = 1 - MACOS = OSX = RALT = 2 - WINC = 3 + NOOP = const(0) + LINUX = IBUS = const(1) + MACOS = OSX = RALT = const(2) + WINC = const(3) diff --git a/kmk/extensions/__init__.py b/kmk/extensions/__init__.py index d41bba8..1eba5e5 100644 --- a/kmk/extensions/__init__.py +++ b/kmk/extensions/__init__.py @@ -8,35 +8,44 @@ class Extension: def enable(self, keyboard): self._enabled = True - self.on_runtime_enable(self, keyboard) + self.on_runtime_enable(keyboard) def disable(self, keyboard): self._enabled = False - self.on_runtime_disable(self, keyboard) + self.on_runtime_disable(keyboard) # The below methods should be implemented by subclasses def on_runtime_enable(self, keyboard): - pass + raise NotImplementedError def on_runtime_disable(self, keyboard): - pass + raise NotImplementedError def during_bootup(self, keyboard): - pass + raise NotImplementedError def before_matrix_scan(self, keyboard): ''' Return value will be injected as an extra matrix update ''' - pass + raise NotImplementedError - def after_matrix_scan(self, keyboard, matrix_update): - pass + def after_matrix_scan(self, keyboard): + ''' + Return value will be replace matrix update if supplied + ''' + raise NotImplementedError def before_hid_send(self, keyboard): - pass + raise NotImplementedError def after_hid_send(self, keyboard): - pass + raise NotImplementedError + + def on_powersave_enable(self, keyboard): + raise NotImplementedError + + def on_powersave_disable(self, keyboard): + raise NotImplementedError diff --git a/kmk/extensions/international.py b/kmk/extensions/international.py new file mode 100644 index 0000000..eab8087 --- /dev/null +++ b/kmk/extensions/international.py @@ -0,0 +1,59 @@ +'''Adds international keys''' +from kmk.extensions import Extension +from kmk.keys import make_key + + +class International(Extension): + '''Adds international keys''' + + def __init__(self): + # International + make_key(code=50, names=('NONUS_HASH', 'NUHS')) + make_key(code=100, names=('NONUS_BSLASH', 'NUBS')) + make_key(code=101, names=('APP', 'APPLICATION', 'SEL', 'WINMENU')) + + make_key(code=135, names=('INT1', 'RO')) + make_key(code=136, names=('INT2', 'KANA')) + make_key(code=137, names=('INT3', 'JYEN')) + make_key(code=138, names=('INT4', 'HENK')) + make_key(code=139, names=('INT5', 'MHEN')) + make_key(code=140, names=('INT6',)) + make_key(code=141, names=('INT7',)) + make_key(code=142, names=('INT8',)) + make_key(code=143, names=('INT9',)) + make_key(code=144, names=('LANG1', 'HAEN')) + make_key(code=145, names=('LANG2', 'HAEJ')) + make_key(code=146, names=('LANG3',)) + make_key(code=147, names=('LANG4',)) + make_key(code=148, names=('LANG5',)) + make_key(code=149, names=('LANG6',)) + make_key(code=150, names=('LANG7',)) + make_key(code=151, names=('LANG8',)) + make_key(code=152, names=('LANG9',)) + + def on_runtime_enable(self, sandbox): + return + + def on_runtime_disable(self, sandbox): + return + + def during_bootup(self, sandbox): + return + + def before_matrix_scan(self, sandbox): + return + + def after_matrix_scan(self, sandbox): + return + + def before_hid_send(self, sandbox): + return + + def after_hid_send(self, sandbox): + return + + def on_powersave_enable(self, sandbox): + return + + def on_powersave_disable(self, sandbox): + return diff --git a/kmk/extensions/leader.py b/kmk/extensions/leader.py deleted file mode 100644 index 8042037..0000000 --- a/kmk/extensions/leader.py +++ /dev/null @@ -1,111 +0,0 @@ -import gc - -from kmk.extensions import Extension, InvalidExtensionEnvironment -from kmk.handlers.stock import passthrough as handler_passthrough -from kmk.keys import KC, make_key - - -class LeaderMode: - TIMEOUT = 0 - TIMEOUT_ACTIVE = 1 - ENTER = 2 - ENTER_ACTIVE = 3 - - -class Leader(Extension): - def __init__(self, mode=LeaderMode.TIMEOUT, timeout=1000, sequences=None): - if sequences is None: - raise InvalidExtensionEnvironment( - 'sequences must be a dictionary, not None' - ) - - self._mode = mode - self._timeout = timeout - self._sequences = self._compile_sequences(sequences) - - self._leader_pending = None - self._assembly_last_len = 0 - self._sequence_assembly = [] - - make_key( - names=('LEADER', 'LEAD'), - on_press=self._key_leader_pressed, - on_release=handler_passthrough, - ) - - gc.collect() - - def after_matrix_scan(self, keyboard_state, *args): - if self._mode % 2 == 1: - keys_pressed = keyboard_state._keys_pressed - - if self._assembly_last_len and self._sequence_assembly: - history_set = set(self._sequence_assembly) - - keys_pressed = keys_pressed - history_set - - self._assembly_last_len = len(keyboard_state._keys_pressed) - - for key in keys_pressed: - if self._mode == LeaderMode.ENTER_ACTIVE and key == KC.ENT: - self._handle_leader_sequence(keyboard_state) - break - elif key == KC.ESC or key == KC.GESC: - # Clean self and turn leader mode off. - self._exit_leader_mode(keyboard_state) - break - elif key == KC.LEAD: - break - else: - # Add key if not needing to escape - # This needs replaced later with a proper debounce - self._sequence_assembly.append(key) - - keyboard_state._hid_pending = False - - def _compile_sequences(self, sequences): - gc.collect() - - for k, v in sequences.items(): - if not isinstance(k, tuple): - new_key = tuple(KC[c] for c in k) - sequences[new_key] = v - - for k, v in sequences.items(): - if not isinstance(k, tuple): - del sequences[k] - - gc.collect() - - return sequences - - def _handle_leader_sequence(self, keyboard_state): - lmh = tuple(self._sequence_assembly) - # Will get caught in infinite processing loops if we don't - # exit leader mode before processing the target key - self._exit_leader_mode(keyboard_state) - - if lmh in self._sequences: - # Stack depth exceeded if try to use add_key here with a unicode sequence - keyboard_state._process_key(self._sequences[lmh], True) - - keyboard_state._set_timeout( - False, lambda: keyboard_state._remove_key(self._sequences[lmh]) - ) - - def _exit_leader_mode(self, keyboard_state): - self._sequence_assembly.clear() - self._mode -= 1 - self._assembly_last_len = 0 - keyboard_state._keys_pressed.clear() - - def _key_leader_pressed(self, key, keyboard_state, *args, **kwargs): - if self._mode % 2 == 0: - keyboard_state._keys_pressed.discard(key) - # All leader modes are one number higher when activating - self._mode += 1 - - if self._mode == LeaderMode.TIMEOUT_ACTIVE: - keyboard_state._set_timeout( - self._timeout, lambda: self._handle_leader_sequence(keyboard_state) - ) diff --git a/kmk/led.py b/kmk/extensions/led.py similarity index 79% rename from kmk/led.py rename to kmk/extensions/led.py index 410d272..6e69e9f 100644 --- a/kmk/led.py +++ b/kmk/extensions/led.py @@ -24,6 +24,7 @@ class LED(Extension): animation_mode=AnimationModes.STATIC, animation_speed=1, user_animation=None, + val=100, ): try: self._led = pulseio.PWMOut(led_pin) @@ -36,12 +37,14 @@ class LED(Extension): self._brightness = 0 self._pos = 0 self._effect_init = False + self._enabled = True self.brightness_step = brightness_step self.brightness_limit = brightness_limit self.animation_mode = animation_mode self.animation_speed = animation_speed self.breathe_center = breathe_center + self.val = val if user_animation is not None: self.user_animation = user_animation @@ -62,20 +65,51 @@ class LED(Extension): return 'LED({})'.format(self._to_dict()) def _to_dict(self): - # TODO FIXME remove - pass + return { + '_brightness': self._brightness, + '_pos': self._pos, + 'brightness_step': self.brightness_step, + 'brightness_limit': self.brightness_limit, + 'animation_mode': self.animation_mode, + 'animation_speed': self.animation_speed, + 'breathe_center': self.breathe_center, + 'val': self.val, + } + + def on_runtime_enable(self, sandbox): + return + + def on_runtime_disable(self, sandbox): + return + + def during_bootup(self, sandbox): + return + + def before_matrix_scan(self, sandbox): + return + + def after_matrix_scan(self, sandbox): + return + + def before_hid_send(self, sandbox): + return + + def after_hid_send(self, sandbox): + if self._enabled and self.animation_mode: + self.animate() + return + + def on_powersave_enable(self, sandbox): + return + + def on_powersave_disable(self, sandbox): + return def _init_effect(self): self._pos = 0 self._effect_init = False return self - def after_hid_send(self, keyboard): - if self._enabled and self.animation_mode: - self.animate() - - return keyboard - def set_brightness(self, percent): self._led.duty_cycle = int(percent / 100 * 65535) @@ -135,13 +169,10 @@ class LED(Extension): self._pos = (self._pos + self.animation_speed) % 256 self.set_brightness(self._brightness) - return self - def effect_static(self): self.set_brightness(self._brightness) # Set animation mode to none to prevent cycles from being wasted self.animation_mode = None - return self def animate(self): ''' @@ -160,37 +191,28 @@ class LED(Extension): else: self.off() - return self - - def _key_led_tog(self, key, state, *args, **kwargs): + def _key_led_tog(self, *args, **kwargs): if self.animation_mode == AnimationModes.STATIC_STANDBY: self.animation_mode = AnimationModes.STATIC self._enabled = not self._enabled - return state - def _key_led_inc(self, key, state, *args, **kwargs): + def _key_led_inc(self, *args, **kwargs): self.increase_brightness() - return state - def _key_led_dec(self, key, state, *args, **kwargs): + def _key_led_dec(self, *args, **kwargs): self.decrease_brightness() - return state - def _key_led_ani(self, key, state, *args, **kwargs): + def _key_led_ani(self, *args, **kwargs): self.increase_ani() - return state - def _key_led_and(self, key, state, *args, **kwargs): + def _key_led_and(self, *args, **kwargs): self.decrease_ani() - return state - def _key_led_mode_static(self, key, state, *args, **kwargs): + def _key_led_mode_static(self, *args, **kwargs): self._effect_init = True self.animation_mode = AnimationModes.STATIC - return state - def _key_led_mode_breathe(self, key, state, *args, **kwargs): + def _key_led_mode_breathe(self, *args, **kwargs): self._effect_init = True self.animation_mode = AnimationModes.BREATHING - return state diff --git a/kmk/extensions/media_keys.py b/kmk/extensions/media_keys.py new file mode 100644 index 0000000..84de64b --- /dev/null +++ b/kmk/extensions/media_keys.py @@ -0,0 +1,55 @@ +from kmk.extensions import Extension +from kmk.keys import make_consumer_key + + +class MediaKeys(Extension): + def __init__(self): + # Consumer ("media") keys. Most known keys aren't supported here. A much + # longer list used to exist in this file, but the codes were almost certainly + # incorrect, conflicting with each other, or otherwise 'weird'. We'll add them + # back in piecemeal as needed. PRs welcome. + # + # A super useful reference for these is http://www.freebsddiary.org/APC/usb_hid_usages.php + # Note that currently we only have the PC codes. Recent MacOS versions seem to + # support PC media keys, so I don't know how much value we would get out of + # adding the old Apple-specific consumer codes, but again, PRs welcome if the + # lack of them impacts you. + make_consumer_key(code=226, names=('AUDIO_MUTE', 'MUTE')) # 0xE2 + make_consumer_key(code=233, names=('AUDIO_VOL_UP', 'VOLU')) # 0xE9 + make_consumer_key(code=234, names=('AUDIO_VOL_DOWN', 'VOLD')) # 0xEA + make_consumer_key(code=181, names=('MEDIA_NEXT_TRACK', 'MNXT')) # 0xB5 + make_consumer_key(code=182, names=('MEDIA_PREV_TRACK', 'MPRV')) # 0xB6 + make_consumer_key(code=183, names=('MEDIA_STOP', 'MSTP')) # 0xB7 + make_consumer_key( + code=205, names=('MEDIA_PLAY_PAUSE', 'MPLY') + ) # 0xCD (this may not be right) + make_consumer_key(code=184, names=('MEDIA_EJECT', 'EJCT')) # 0xB8 + make_consumer_key(code=179, names=('MEDIA_FAST_FORWARD', 'MFFD')) # 0xB3 + make_consumer_key(code=180, names=('MEDIA_REWIND', 'MRWD')) # 0xB4 + + def on_runtime_enable(self, sandbox): + return + + def on_runtime_disable(self, sandbox): + return + + def during_bootup(self, sandbox): + return + + def before_matrix_scan(self, sandbox): + return + + def after_matrix_scan(self, sandbox): + return + + def before_hid_send(self, sandbox): + return + + def after_hid_send(self, sandbox): + return + + def on_powersave_enable(self, sandbox): + return + + def on_powersave_disable(self, sandbox): + return diff --git a/kmk/rgb.py b/kmk/extensions/rgb.py similarity index 60% rename from kmk/rgb.py rename to kmk/extensions/rgb.py index eeab9a6..93c4312 100644 --- a/kmk/rgb.py +++ b/kmk/extensions/rgb.py @@ -4,6 +4,8 @@ import time from math import e, exp, pi, sin from kmk.extensions import Extension +from kmk.handlers.stock import passthrough as handler_passthrough +from kmk.keys import make_key rgb_config = {} @@ -13,7 +15,11 @@ class AnimationModes: STATIC = 1 STATIC_STANDBY = 2 BREATHING = 3 - USER = 4 + RAINBOW = 4 + BREATHING_RAINBOW = 5 + KNIGHT = 6 + SWIRL = 7 + USER = 8 class RGB(Extension): @@ -25,22 +31,23 @@ class RGB(Extension): self, pixel_pin, num_pixels=0, - val_limit=255, + val_limit=100, hue_default=0, sat_default=100, rgb_order=(1, 0, 2), # GRB WS2812 val_default=100, - hue_step=1, - sat_step=1, - val_step=1, + hue_step=5, + sat_step=5, + val_step=5, animation_speed=1, - breathe_center=1.5, # 1.0-2.7 + breathe_center=1, # 1.0-2.7 knight_effect_length=3, animation_mode=AnimationModes.STATIC, effect_init=False, reverse_animation=False, user_animation=None, disable_auto_write=False, + loopcounter=0, ): self.neopixel = neopixel.NeoPixel( pixel_pin, @@ -49,38 +56,121 @@ class RGB(Extension): auto_write=not disable_auto_write, ) - if len(rgb_order) == 4: - self.rgbw = True + self.rgbw = bool(len(rgb_order) == 4) self.num_pixels = num_pixels self.hue_step = hue_step self.sat_step = sat_step self.val_step = val_step self.hue = hue_default + self.hue_default = hue_default self.sat = sat_default + self.sat_default = sat_default self.val = val_default + self.val_default = val_default self.breathe_center = breathe_center self.knight_effect_length = knight_effect_length self.val_limit = val_limit self.animation_mode = animation_mode self.animation_speed = animation_speed + self.effect_init = effect_init self.reverse_animation = reverse_animation self.user_animation = user_animation self.disable_auto_write = disable_auto_write + self.loopcounter = loopcounter - def during_bootup(self, keyboard): - pass + make_key( + names=('RGB_TOG',), on_press=self._rgb_tog, on_release=handler_passthrough + ) + make_key( + names=('RGB_HUI',), on_press=self._rgb_hui, on_release=handler_passthrough + ) + make_key( + names=('RGB_HUD',), on_press=self._rgb_hud, on_release=handler_passthrough + ) + make_key( + names=('RGB_SAI',), on_press=self._rgb_sai, on_release=handler_passthrough + ) + make_key( + names=('RGB_SAD',), on_press=self._rgb_sad, on_release=handler_passthrough + ) + make_key( + names=('RGB_VAI',), on_press=self._rgb_vai, on_release=handler_passthrough + ) + make_key( + names=('RGB_VAD',), on_press=self._rgb_vad, on_release=handler_passthrough + ) + make_key( + names=('RGB_ANI',), on_press=self._rgb_ani, on_release=handler_passthrough + ) + make_key( + names=('RGB_AND',), on_press=self._rgb_and, on_release=handler_passthrough + ) + make_key( + names=('RGB_MODE_PLAIN', 'RGB_M_P'), + on_press=self._rgb_mode_static, + on_release=handler_passthrough, + ) + make_key( + names=('RGB_MODE_BREATHE', 'RGB_M_B'), + on_press=self._rgb_mode_breathe, + on_release=handler_passthrough, + ) + make_key( + names=('RGB_MODE_RAINBOW', 'RGB_M_R'), + on_press=self._rgb_mode_rainbow, + on_release=handler_passthrough, + ) + make_key( + names=('RGB_MODE_BREATHE_RAINBOW', 'RGB_M_BR'), + on_press=self._rgb_mode_breathe_rainbow, + on_release=handler_passthrough, + ) + make_key( + names=('RGB_MODE_SWIRL', 'RGB_M_S'), + on_press=self._rgb_mode_swirl, + on_release=handler_passthrough, + ) + make_key( + names=('RGB_MODE_KNIGHT', 'RGB_M_K'), + on_press=self._rgb_mode_knight, + on_release=handler_passthrough, + ) + make_key( + names=('RGB_RESET', 'RGB_RST'), + on_press=self._rgb_reset, + on_release=handler_passthrough, + ) - def after_hid_send(self, keyboard): - if self.animation_mode: - self.loopcounter += 1 - if self.loopcounter >= 7: - self.animate() - self.loopcounter = 0 + def on_runtime_enable(self, sandbox): + return - return keyboard + def on_runtime_disable(self, sandbox): + return - def time_ms(self): + def during_bootup(self, sandbox): + return + + def before_matrix_scan(self, sandbox): + return + + def after_matrix_scan(self, sandbox): + return + + def before_hid_send(self, sandbox): + return + + def after_hid_send(self, sandbox): + self.animate() + + def on_powersave_enable(self, sandbox): + return + + def on_powersave_disable(self, sandbox): + self._do_update() + + @staticmethod + def time_ms(): return int(time.monotonic() * 1000) def hsv_to_rgb(self, hue, sat, val): @@ -105,7 +195,7 @@ class RGB(Extension): else: base = ((100 - sat) * val) / 100 - color = int((val - base) * ((hue % 60) / 60)) + color = (val - base) * ((hue % 60) / 60) x = int(hue / 60) if x == 0: @@ -160,8 +250,6 @@ class RGB(Extension): else: self.set_rgb(self.hsv_to_rgb(hue, sat, val), index) - return self - def set_hsv_fill(self, hue, sat, val): ''' Takes HSV values and displays it on all LEDs/Neopixels @@ -174,7 +262,6 @@ class RGB(Extension): self.set_rgb_fill(self.hsv_to_rgbw(hue, sat, val)) else: self.set_rgb_fill(self.hsv_to_rgb(hue, sat, val)) - return self def set_rgb(self, rgb, index): ''' @@ -187,8 +274,6 @@ class RGB(Extension): if not self.disable_auto_write: self.neopixel.show() - return self - def set_rgb_fill(self, rgb): ''' Takes an RGB or RGBW and displays it on all LEDs/Neopixels @@ -199,8 +284,6 @@ class RGB(Extension): if not self.disable_auto_write: self.neopixel.show() - return self - def increase_hue(self, step=None): ''' Increases hue by step amount rolling at 360 and returning to 0 @@ -214,8 +297,6 @@ class RGB(Extension): if self._check_update(): self._do_update() - return self - def decrease_hue(self, step=None): ''' Decreases hue by step amount rolling at 0 and returning to 360 @@ -232,8 +313,6 @@ class RGB(Extension): if self._check_update(): self._do_update() - return self - def increase_sat(self, step=None): ''' Increases saturation by step amount stopping at 100 @@ -250,8 +329,6 @@ class RGB(Extension): if self._check_update(): self._do_update() - return self - def decrease_sat(self, step=None): ''' Decreases saturation by step amount stopping at 0 @@ -268,8 +345,6 @@ class RGB(Extension): if self._check_update(): self._do_update() - return self - def increase_val(self, step=None): ''' Increases value by step amount stopping at 100 @@ -285,8 +360,6 @@ class RGB(Extension): if self._check_update(): self._do_update() - return self - def decrease_val(self, step=None): ''' Decreases value by step amount stopping at 0 @@ -302,8 +375,6 @@ class RGB(Extension): if self._check_update(): self._do_update() - return self - def increase_ani(self): ''' Increases animation speed by 1 amount stopping at 10 @@ -316,8 +387,6 @@ class RGB(Extension): if self._check_update(): self._do_update() - return self - def decrease_ani(self): ''' Decreases animation speed by 1 amount stopping at 0 @@ -330,8 +399,6 @@ class RGB(Extension): if self._check_update(): self._do_update() - return self - def off(self): ''' Turns off all LEDs/Neopixels without changing stored values @@ -339,8 +406,6 @@ class RGB(Extension): if self.neopixel: self.set_hsv_fill(0, 0, 0) - return self - def show(self): ''' Turns on all LEDs/Neopixels without changing stored values @@ -348,8 +413,6 @@ class RGB(Extension): if self.neopixel: self.neopixel.show() - return self - def animate(self): ''' Activates a "step" in the animation based on the active mode @@ -358,27 +421,30 @@ class RGB(Extension): if self.effect_init: self._init_effect() - if self.enabled: - if self.animation_mode == 'breathing': - return self.effect_breathing() - elif self.animation_mode == 'rainbow': - return self.effect_rainbow() - elif self.animation_mode == 'breathing_rainbow': - return self.effect_breathing_rainbow() - elif self.animation_mode == 'static': - return self.effect_static() - elif self.animation_mode == 'knight': - return self.effect_knight() - elif self.animation_mode == 'swirl': - return self.effect_swirl() - elif self.animation_mode == 'user': - return self.user_animation(self) - elif self.animation_mode == 'static_standby': - pass - else: - self.off() - - return self + if self.animation_mode is not AnimationModes.STATIC_STANDBY: + self.loopcounter += 1 + if self.loopcounter >= 7 and self.enable: + self.loopcounter = 0 + if self.animation_mode == AnimationModes.BREATHING: + self.effect_breathing() + elif self.animation_mode == AnimationModes.RAINBOW: + self.effect_rainbow() + elif self.animation_mode == AnimationModes.BREATHING_RAINBOW: + self.effect_breathing_rainbow() + elif self.animation_mode == AnimationModes.STATIC: + self.effect_static() + elif self.animation_mode == AnimationModes.KNIGHT: + self.effect_knight() + elif self.animation_mode == AnimationModes.SWIRL: + self.effect_swirl() + elif self.animation_mode == AnimationModes.USER: + self.user_animation(self) + elif self.animation_mode == AnimationModes.STATIC_STANDBY: + pass + else: + self.off() + if self.loopcounter >= 7: + self.loopcounter = 0 def _animation_step(self): interval = self.time_ms() - self.time @@ -387,35 +453,31 @@ class RGB(Extension): return max(self.intervals) if interval in self.intervals: return interval - else: - return False + return None def _init_effect(self): if ( - self.animation_mode == 'breathing' - or self.animation_mode == 'breathing_rainbow' + self.animation_mode == AnimationModes.BREATHING + or self.animation_mode == AnimationModes.BREATHING_RAINBOW ): self.intervals = (30, 20, 10, 5) - elif self.animation_mode == 'swirl': + elif self.animation_mode == AnimationModes.SWIRL: self.intervals = (50, 50) self.pos = 0 self.reverse_animation = False self.effect_init = False - return self def _check_update(self): - if self.animation_mode == 'static_standby': - return True + return bool(self.animation_mode == AnimationModes.STATIC_STANDBY) def _do_update(self): - if self.animation_mode == 'static_standby': - self.animation_mode = 'static' + if self.animation_mode == AnimationModes.STATIC_STANDBY: + self.animation_mode = AnimationModes.STATIC def effect_static(self): self.set_hsv_fill(self.hue, self.sat, self.val) - self.animation_mode = 'static_standby' - return self + self.animation_mode = AnimationModes.STATIC_STANDBY def effect_breathing(self): # http://sean.voisen.org/blog/2011/10/breathing-led-with-arduino/ @@ -428,20 +490,14 @@ class RGB(Extension): self.pos = (self.pos + self.animation_speed) % 256 self.set_hsv_fill(self.hue, self.sat, self.val) - return self - def effect_breathing_rainbow(self): self.increase_hue(self.animation_speed) self.effect_breathing() - return self - def effect_rainbow(self): self.increase_hue(self.animation_speed) self.set_hsv_fill(self.hue, self.sat, self.val) - return self - def effect_swirl(self): self.increase_hue(self.animation_speed) self.disable_auto_write = True # Turn off instantly showing @@ -453,7 +509,6 @@ class RGB(Extension): # Show final results self.disable_auto_write = False # Resume showing changes self.show() - return self def effect_knight(self): # Determine which LEDs should be lit up @@ -478,4 +533,69 @@ class RGB(Extension): self.disable_auto_write = False # Resume showing changes self.show() - return self + def _rgb_tog(self, *args, **kwargs): + if self.animation_mode == AnimationModes.STATIC: + self.animation_mode = AnimationModes.STATIC_STANDBY + self._do_update() + if self.animation_mode == AnimationModes.STATIC_STANDBY: + self.animation_mode = AnimationModes.STATIC + self._do_update() + if self.enable: + self.off() + self.enable = not self.enable + + def _rgb_hui(self, *args, **kwargs): + self.increase_hue() + + def _rgb_hud(self, *args, **kwargs): + self.decrease_hue() + + def _rgb_sai(self, *args, **kwargs): + self.increase_sat() + + def _rgb_sad(self, *args, **kwargs): + self.decrease_sat() + + def _rgb_vai(self, *args, **kwargs): + self.increase_val() + + def _rgb_vad(self, *args, **kwargs): + self.decrease_val() + + def _rgb_ani(self, *args, **kwargs): + self.increase_ani() + + def _rgb_and(self, *args, **kwargs): + self.decrease_ani() + + def _rgb_mode_static(self, *args, **kwargs): + self.effect_init = True + self.animation_mode = AnimationModes.STATIC + + def _rgb_mode_breathe(self, *args, **kwargs): + self.effect_init = True + self.animation_mode = AnimationModes.BREATHING + + def _rgb_mode_breathe_rainbow(self, *args, **kwargs): + self.effect_init = True + self.animation_mode = AnimationModes.BREATHING_RAINBOW + + def _rgb_mode_rainbow(self, *args, **kwargs): + self.effect_init = True + self.animation_mode = AnimationModes.RAINBOW + + def _rgb_mode_swirl(self, *args, **kwargs): + self.effect_init = True + self.animation_mode = AnimationModes.SWIRL + + def _rgb_mode_knight(self, *args, **kwargs): + self.effect_init = True + self.animation_mode = AnimationModes.KNIGHT + + def _rgb_reset(self, *args, **kwargs): + self.hue = self.hue_default + self.sat = self.sat_default + self.val = self.val_default + if self.animation_mode == AnimationModes.STATIC_STANDBY: + self.animation_mode = AnimationModes.STATIC + self._do_update() diff --git a/kmk/extensions/split.py b/kmk/extensions/split.py deleted file mode 100644 index 3ea5905..0000000 --- a/kmk/extensions/split.py +++ /dev/null @@ -1,103 +0,0 @@ -import busio -import gc - -from kmk.extensions import Extension -from kmk.kmktime import sleep_ms -from kmk.matrix import intify_coordinate - - -class SplitType: - UART = 1 - I2C = 2 # unused - ONEWIRE = 3 # unused - BLE = 4 # unused - - -class Split(Extension): - def __init__( - self, - extra_data_pin=None, - offsets=(), - flip=False, - side=None, - stype=None, - master_left=True, - uart_flip=True, - uart_pin=None, - uart_timeout=20, - ): - self.extra_data_pin = extra_data_pin - self.split_offsets = offsets - self.split_flip = flip - self.split_side = side - self.split_type = stype - self.split_master_left = master_left - self._uart = None - self.uart_flip = uart_flip - self.uart_pin = uart_pin - self.uart_timeout = uart_timeout - - def during_bootup(self, keyboard): - if self.split_type is not None: - try: - # Working around https://github.com/adafruit/circuitpython/issues/1769 - keyboard._hid_helper_inst.create_report([]).send() - self._is_master = True - - # Sleep 2s so master portion doesn't "appear" to boot quicker than - # dependent portions (which will take ~2s to time out on the HID send) - sleep_ms(2000) - except OSError: - self._is_master = False - - if self.split_flip and not self._is_master: - keyboard.col_pins = list(reversed(self.col_pins)) - if self.split_side == 'Left': - self.split_master_left = self._is_master - elif self.split_side == 'Right': - self.split_master_left = not self._is_master - else: - self._is_master = True - - if self.uart_pin is not None: - if self._is_master: - self._uart = busio.UART( - tx=None, rx=self.uart_pin, timeout=self.uart_timeout - ) - else: - self._uart = busio.UART( - tx=self.uart_pin, rx=None, timeout=self.uart_timeout - ) - - # Attempt to sanely guess a coord_mapping if one is not provided. - if not keyboard.coord_mapping: - keyboard.coord_mapping = [] - - rows_to_calc = len(keyboard.row_pins) - cols_to_calc = len(keyboard.col_pins) - - if self.split_offsets: - rows_to_calc *= 2 - cols_to_calc *= 2 - - for ridx in range(rows_to_calc): - for cidx in range(cols_to_calc): - keyboard.coord_mapping.append(intify_coordinate(ridx, cidx)) - - gc.collect() - - def before_matrix_scan(self, keyboard_state): - if self.split_type is not None and self._is_master: - return self._receive_from_slave() - - def after_matrix_scan(self, keyboard_state, matrix_update): - if matrix_update is not None and not self._is_master: - self._send_to_master(matrix_update) - - def _send_to_master(self, update): - if self.split_master_left: - update[1] += self.split_offsets[update[0]] - else: - update[1] -= self.split_offsets[update[0]] - if self._uart is not None: - self._uart.write(update) diff --git a/kmk/handlers/layers.py b/kmk/handlers/layers.py deleted file mode 100644 index fa33fc1..0000000 --- a/kmk/handlers/layers.py +++ /dev/null @@ -1,124 +0,0 @@ -from kmk.kmktime import ticks_diff, ticks_ms - - -def df_pressed(key, state, *args, **kwargs): - ''' - Switches the default layer - ''' - state._active_layers[-1] = key.meta.layer - return state - - -def mo_pressed(key, state, *args, **kwargs): - ''' - Momentarily activates layer, switches off when you let go - ''' - state._active_layers.insert(0, key.meta.layer) - return state - - -def mo_released(key, state, KC, *args, **kwargs): - # remove the first instance of the target layer - # from the active list - # under almost all normal use cases, this will - # disable the layer (but preserve it if it was triggered - # as a default layer, etc.) - # this also resolves an issue where using DF() on a layer - # triggered by MO() and then defaulting to the MO()'s layer - # would result in no layers active - try: - del_idx = state._active_layers.index(key.meta.layer) - del state._active_layers[del_idx] - except ValueError: - pass - - return state - - -def lm_pressed(key, state, *args, **kwargs): - ''' - As MO(layer) but with mod active - ''' - state._hid_pending = True - # Sets the timer start and acts like MO otherwise - state._start_time['lm'] = ticks_ms() - state._keys_pressed.add(key.meta.kc) - return mo_pressed(key, state, *args, **kwargs) - - -def lm_released(key, state, *args, **kwargs): - ''' - As MO(layer) but with mod active - ''' - state._hid_pending = True - state._keys_pressed.discard(key.meta.kc) - state._start_time['lm'] = None - return mo_released(key, state, *args, **kwargs) - - -def lt_pressed(key, state, *args, **kwargs): - # Sets the timer start and acts like MO otherwise - state._start_time['lt'] = ticks_ms() - return mo_pressed(key, state, *args, **kwargs) - - -def lt_released(key, state, *args, **kwargs): - # On keyup, check timer, and press key if needed. - if state._start_time['lt'] and ( - ticks_diff(ticks_ms(), state._start_time['lt']) < state.tap_time - ): - state._hid_pending = True - state._tap_key(key.meta.kc) - - mo_released(key, state, *args, **kwargs) - state._start_time['lt'] = None - return state - - -def tg_pressed(key, state, *args, **kwargs): - ''' - Toggles the layer (enables it if not active, and vise versa) - ''' - # See mo_released for implementation details around this - try: - del_idx = state._active_layers.index(key.meta.layer) - del state._active_layers[del_idx] - except ValueError: - state._active_layers.insert(0, key.meta.layer) - - return state - - -def to_pressed(key, state, *args, **kwargs): - ''' - Activates layer and deactivates all other layers - ''' - state._active_layers.clear() - state._active_layers.insert(0, key.meta.layer) - - return state - - -def tt_pressed(key, state, *args, **kwargs): - ''' - Momentarily activates layer if held, toggles it if tapped repeatedly - ''' - # TODO Make this work with tap dance to function more correctly, but technically works. - if state._start_time['tt'] is None: - # Sets the timer start and acts like MO otherwise - state._start_time['tt'] = ticks_ms() - return mo_pressed(key, state, *args, **kwargs) - elif ticks_diff(ticks_ms(), state._start_time['tt']) < state.tap_time: - state._start_time['tt'] = None - return tg_pressed(key, state, *args, **kwargs) - - -def tt_released(key, state, *args, **kwargs): - tap_timed_out = ticks_diff(ticks_ms(), state._start_time['tt']) >= state.tap_time - if state._start_time['tt'] is None or tap_timed_out: - # On first press, works like MO. On second press, does nothing unless let up within - # time window, then acts like TG. - state._start_time['tt'] = None - return mo_released(key, state, *args, **kwargs) - - return state diff --git a/kmk/handlers/modtap.py b/kmk/handlers/modtap.py deleted file mode 100644 index 9d3dc5f..0000000 --- a/kmk/handlers/modtap.py +++ /dev/null @@ -1,23 +0,0 @@ -from kmk.kmktime import ticks_diff, ticks_ms - - -def mt_pressed(key, state, *args, **kwargs): - # Sets the timer start and acts like a modifier otherwise - state._keys_pressed.add(key.meta.mods) - - state._start_time['mod_tap'] = ticks_ms() - return state - - -def mt_released(key, state, *args, **kwargs): - # On keyup, check timer, and press key if needed. - state._keys_pressed.discard(key.meta.mods) - timer_name = 'mod_tap' - if state._start_time[timer_name] and ( - ticks_diff(ticks_ms(), state._start_time[timer_name]) < state.tap_time - ): - state._hid_pending = True - state._tap_key(key.meta.kc) - - state._start_time[timer_name] = None - return state diff --git a/kmk/handlers/sequences.py b/kmk/handlers/sequences.py index b079421..5ac5028 100644 --- a/kmk/handlers/sequences.py +++ b/kmk/handlers/sequences.py @@ -1,3 +1,5 @@ +import gc + from kmk.consts import UnicodeMode from kmk.handlers.stock import passthrough from kmk.keys import KC, make_key @@ -11,21 +13,21 @@ def get_wide_ordinal(char): return 0x10000 + (ord(char[0]) - 0xD800) * 0x400 + (ord(char[1]) - 0xDC00) -def sequence_press_handler(key, state, KC, *args, **kwargs): - old_keys_pressed = state._keys_pressed - state._keys_pressed = set() +def sequence_press_handler(key, keyboard, KC, *args, **kwargs): + oldkeys_pressed = keyboard.keys_pressed + keyboard.keys_pressed = set() for ikey in key.meta.seq: if not getattr(ikey, 'no_press', None): - state._process_key(ikey, True) - state._send_hid() + keyboard.process_key(ikey, True) + keyboard._send_hid() if not getattr(ikey, 'no_release', None): - state._process_key(ikey, False) - state._send_hid() + keyboard.process_key(ikey, False) + keyboard._send_hid() - state._keys_pressed = old_keys_pressed + keyboard.keys_pressed = oldkeys_pressed - return state + return keyboard def simple_key_sequence(seq): @@ -59,10 +61,23 @@ RALT_UP_NO_PRESS = simple_key_sequence((KC.RALT(no_press=True),)) def compile_unicode_string_sequences(string_table): - for k, v in string_table.items(): - string_table[k] = unicode_string_sequence(v) + ''' + Destructively convert ("compile") unicode strings into key sequences. This + will, for RAM saving reasons, empty the input dictionary and trigger + garbage collection. + ''' + target = AttrDict() - return AttrDict(string_table) + for k, v in string_table.items(): + target[k] = unicode_string_sequence(v) + + # now loop through and kill the input dictionary to save RAM + for k in target.keys(): + del string_table[k] + + gc.collect() + + return target def unicode_string_sequence(unistring): @@ -82,9 +97,6 @@ def generate_codepoint_keysym_seq(codepoint, expected_length=4): # Not sure how to send emojis on Mac/Windows like that, # though, since (for example) the Canadian flag is assembled # from two five-character codepoints, 1f1e8 and 1f1e6 - # - # As a bonus, this function can be pretty useful for - # leader dictionary keys as strings. seq = [KC.N0 for _ in range(max(len(codepoint), expected_length))] for idx, codepoint_fragment in enumerate(reversed(codepoint)): @@ -93,47 +105,43 @@ def generate_codepoint_keysym_seq(codepoint, expected_length=4): return seq -def generate_leader_dictionary_seq(string): - return tuple(generate_codepoint_keysym_seq(string, 1)) - - def unicode_codepoint_sequence(codepoints): kc_seqs = (generate_codepoint_keysym_seq(codepoint) for codepoint in codepoints) kc_macros = [simple_key_sequence(kc_seq) for kc_seq in kc_seqs] - def _unicode_sequence(key, state, *args, **kwargs): - if state.unicode_mode == UnicodeMode.IBUS: - state._process_key( - simple_key_sequence(_ibus_unicode_sequence(kc_macros, state)), True + def _unicode_sequence(key, keyboard, *args, **kwargs): + if keyboard.unicode_mode == UnicodeMode.IBUS: + keyboard.process_key( + simple_key_sequence(_ibus_unicode_sequence(kc_macros, keyboard)), True ) - elif state.unicode_mode == UnicodeMode.RALT: - state._process_key( - simple_key_sequence(_ralt_unicode_sequence(kc_macros, state)), True + elif keyboard.unicode_mode == UnicodeMode.RALT: + keyboard.process_key( + simple_key_sequence(_ralt_unicode_sequence(kc_macros, keyboard)), True ) - elif state.unicode_mode == UnicodeMode.WINC: - state._process_key( - simple_key_sequence(_winc_unicode_sequence(kc_macros, state)), True + elif keyboard.unicode_mode == UnicodeMode.WINC: + keyboard.process_key( + simple_key_sequence(_winc_unicode_sequence(kc_macros, keyboard)), True ) return make_key(on_press=_unicode_sequence) -def _ralt_unicode_sequence(kc_macros, state): +def _ralt_unicode_sequence(kc_macros, keyboard): for kc_macro in kc_macros: yield RALT_DOWN_NO_RELEASE yield kc_macro yield RALT_UP_NO_PRESS -def _ibus_unicode_sequence(kc_macros, state): +def _ibus_unicode_sequence(kc_macros, keyboard): for kc_macro in kc_macros: yield IBUS_KEY_COMBO yield kc_macro yield ENTER_KEY -def _winc_unicode_sequence(kc_macros, state): +def _winc_unicode_sequence(kc_macros, keyboard): ''' Send unicode sequence using WinCompose: diff --git a/kmk/handlers/stock.py b/kmk/handlers/stock.py index 7a8edb7..73069b8 100644 --- a/kmk/handlers/stock.py +++ b/kmk/handlers/stock.py @@ -1,213 +1,129 @@ from kmk.kmktime import sleep_ms -def passthrough(key, state, *args, **kwargs): - return state +def passthrough(key, keyboard, *args, **kwargs): + return keyboard -def default_pressed(key, state, KC, coord_int=None, coord_raw=None): - state._hid_pending = True +def default_pressed(key, keyboard, KC, coord_int=None, coord_raw=None, *args, **kwargs): + keyboard.hid_pending = True if coord_int is not None: - state._coord_keys_pressed[coord_int] = key + keyboard._coordkeys_pressed[coord_int] = key - state._keys_pressed.add(key) + keyboard.keys_pressed.add(key) - return state + return keyboard -def default_released(key, state, KC, coord_int=None, coord_raw=None): - state._hid_pending = True - state._keys_pressed.discard(key) +def default_released( + key, keyboard, KC, coord_int=None, coord_raw=None, *args, **kwargs # NOQA +): + keyboard.hid_pending = True + keyboard.keys_pressed.discard(key) if coord_int is not None: - state._keys_pressed.discard(state._coord_keys_pressed.get(coord_int, None)) - state._coord_keys_pressed[coord_int] = None + keyboard.keys_pressed.discard(keyboard._coordkeys_pressed.get(coord_int, None)) + keyboard._coordkeys_pressed[coord_int] = None - return state + return keyboard def reset(*args, **kwargs): - try: - import machine + import microcontroller - machine.reset() - - except ImportError: - import microcontroller - - microcontroller.reset() + microcontroller.reset() def bootloader(*args, **kwargs): - try: - import machine + import microcontroller - machine.bootloader() - - except ImportError: - import microcontroller - - microcontroller.on_next_reset(microcontroller.RunMode.BOOTLOADER) - microcontroller.reset() + microcontroller.on_next_reset(microcontroller.RunMode.BOOTLOADER) + microcontroller.reset() -def debug_pressed(key, state, KC, *args, **kwargs): - if state.debug_enabled: +def debug_pressed(key, keyboard, KC, *args, **kwargs): + if keyboard.debug_enabled: print('DebugDisable()') else: print('DebugEnable()') - state.debug_enabled = not state.debug_enabled + keyboard.debug_enabled = not keyboard.debug_enabled - return state + return keyboard -def gesc_pressed(key, state, KC, *args, **kwargs): +def gesc_pressed(key, keyboard, KC, *args, **kwargs): GESC_TRIGGERS = {KC.LSHIFT, KC.RSHIFT, KC.LGUI, KC.RGUI} - if GESC_TRIGGERS.intersection(state._keys_pressed): + if GESC_TRIGGERS.intersection(keyboard.keys_pressed): # First, release GUI if already pressed - state._send_hid() + keyboard._send_hid() # if Shift is held, KC_GRAVE will become KC_TILDE on OS level - state._keys_pressed.add(KC.GRAVE) - state._hid_pending = True - return state + keyboard.keys_pressed.add(KC.GRAVE) + keyboard.hid_pending = True + return keyboard # else return KC_ESC - state._keys_pressed.add(KC.ESCAPE) - state._hid_pending = True + keyboard.keys_pressed.add(KC.ESCAPE) + keyboard.hid_pending = True - return state + return keyboard -def gesc_released(key, state, KC, *args, **kwargs): - state._keys_pressed.discard(KC.ESCAPE) - state._keys_pressed.discard(KC.GRAVE) - state._hid_pending = True - return state +def gesc_released(key, keyboard, KC, *args, **kwargs): + keyboard.keys_pressed.discard(KC.ESCAPE) + keyboard.keys_pressed.discard(KC.GRAVE) + keyboard.hid_pending = True + return keyboard -def bkdl_pressed(key, state, KC, *args, **kwargs): +def bkdl_pressed(key, keyboard, KC, *args, **kwargs): BKDL_TRIGGERS = {KC.LGUI, KC.RGUI} - if BKDL_TRIGGERS.intersection(state._keys_pressed): - state._send_hid() - state._keys_pressed.add(KC.DEL) - state._hid_pending = True - return state + if BKDL_TRIGGERS.intersection(keyboard.keys_pressed): + keyboard._send_hid() + keyboard.keys_pressed.add(KC.DEL) + keyboard.hid_pending = True + return keyboard # else return KC_ESC - state._keys_pressed.add(KC.BKSP) - state._hid_pending = True + keyboard.keys_pressed.add(KC.BKSP) + keyboard.hid_pending = True - return state + return keyboard -def bkdl_released(key, state, KC, *args, **kwargs): - state._keys_pressed.discard(KC.BKSP) - state._keys_pressed.discard(KC.DEL) - state._hid_pending = True - return state +def bkdl_released(key, keyboard, KC, *args, **kwargs): + keyboard.keys_pressed.discard(KC.BKSP) + keyboard.keys_pressed.discard(KC.DEL) + keyboard.hid_pending = True + return keyboard -def sleep_pressed(key, state, KC, *args, **kwargs): +def sleep_pressed(key, keyboard, KC, *args, **kwargs): sleep_ms(key.meta.ms) - return state + return keyboard -def uc_mode_pressed(key, state, *args, **kwargs): - state.unicode_mode = key.meta.mode +def uc_mode_pressed(key, keyboard, *args, **kwargs): + keyboard.unicode_mode = key.meta.mode - return state + return keyboard -def td_pressed(key, state, *args, **kwargs): - return state._process_tap_dance(key, True) +def td_pressed(key, keyboard, *args, **kwargs): + return keyboard._process_tap_dance(key, True) -def td_released(key, state, *args, **kwargs): - return state._process_tap_dance(key, False) +def td_released(key, keyboard, *args, **kwargs): + return keyboard._process_tap_dance(key, False) -def rgb_tog(key, state, *args, **kwargs): - if state.pixels.animation_mode == 'static_standby': - state.pixels.animation_mode = 'static' - state.pixels.enabled = not state.pixels.enabled - return state - - -def rgb_hui(key, state, *args, **kwargs): - state.pixels.increase_hue() - return state - - -def rgb_hud(key, state, *args, **kwargs): - state.pixels.decrease_hue() - return state - - -def rgb_sai(key, state, *args, **kwargs): - state.pixels.increase_sat() - return state - - -def rgb_sad(key, state, *args, **kwargs): - state.pixels.decrease_sat() - return state - - -def rgb_vai(key, state, *args, **kwargs): - state.pixels.increase_val() - return state - - -def rgb_vad(key, state, *args, **kwargs): - state.pixels.decrease_val() - return state - - -def rgb_ani(key, state, *args, **kwargs): - state.pixels.increase_ani() - return state - - -def rgb_and(key, state, *args, **kwargs): - state.pixels.decrease_ani() - return state - - -def rgb_mode_static(key, state, *args, **kwargs): - state.pixels.effect_init = True - state.pixels.animation_mode = 'static' - return state - - -def rgb_mode_breathe(key, state, *args, **kwargs): - state.pixels.effect_init = True - state.pixels.animation_mode = 'breathing' - return state - - -def rgb_mode_breathe_rainbow(key, state, *args, **kwargs): - state.pixels.effect_init = True - state.pixels.animation_mode = 'breathing_rainbow' - return state - - -def rgb_mode_rainbow(key, state, *args, **kwargs): - state.pixels.effect_init = True - state.pixels.animation_mode = 'rainbow' - return state - - -def rgb_mode_swirl(key, state, *args, **kwargs): - state.pixels.effect_init = True - state.pixels.animation_mode = 'swirl' - return state - - -def rgb_mode_knight(key, state, *args, **kwargs): - state.pixels.effect_init = True - state.pixels.animation_mode = 'knight' - return state +def hid_switch(key, keyboard, *args, **kwargs): + keyboard.hid_type, keyboard.secondary_hid_type = ( + keyboard.secondary_hid_type, + keyboard.hid_type, + ) + keyboard._init_hid() + return keyboard diff --git a/kmk/hid.py b/kmk/hid.py index 62bdf13..c46582c 100644 --- a/kmk/hid.py +++ b/kmk/hid.py @@ -1,12 +1,22 @@ import usb_hid +from micropython import const from kmk.keys import FIRST_KMK_INTERNAL_KEY, ConsumerKey, ModifierKey +from storage import getmount + +try: + from adafruit_ble import BLERadio + from adafruit_ble.advertising.standard import ProvideServicesAdvertisement + from adafruit_ble.services.standard.hid import HIDService +except ImportError: + # BLE not supported on this platform + pass class HIDModes: NOOP = 0 # currently unused; for testing? USB = 1 - BLE = 2 # currently unused; for bluetooth + BLE = 2 ALL_MODES = (NOOP, USB, BLE) @@ -41,7 +51,7 @@ HID_REPORT_SIZES = { class AbstractHID: REPORT_BYTES = 8 - def __init__(self, **kwargs): + def __init__(self): self._evt = bytearray(self.REPORT_BYTES) self.report_device = memoryview(self._evt)[0:1] self.report_device[0] = HIDReportTypes.KEYBOARD @@ -55,7 +65,7 @@ class AbstractHID: self.report_mods = memoryview(self._evt)[1:2] self.report_non_mods = memoryview(self._evt)[3:] - self.post_init(**kwargs) + self.post_init() def __repr__(self): return '{}(REPORT_BYTES={})'.format(self.__class__.__name__, self.REPORT_BYTES) @@ -191,7 +201,7 @@ class AbstractHID: class USBHID(AbstractHID): REPORT_BYTES = 9 - def post_init(self, **kwargs): + def post_init(self): self.devices = {} for device in usb_hid.devices: @@ -221,3 +231,100 @@ class USBHID(AbstractHID): return self.devices[reporting_device_const].send_report( evt[1 : HID_REPORT_SIZES[reporting_device_const] + 1] ) + + +class BLEHID(AbstractHID): + BLE_APPEARANCE_HID_KEYBOARD = const(961) + # Hardcoded in CPy + MAX_CONNECTIONS = const(2) + + def post_init(self, ble_name=str(getmount('/').label), **kwargs): + self.conn_id = -1 + + self.ble = BLERadio() + self.ble.name = ble_name + self.hid = HIDService() + self.hid.protocol_mode = 0 # Boot protocol + + # Security-wise this is not right. While you're away someone turns + # on your keyboard and they can pair with it nice and clean and then + # listen to keystrokes. + # On the other hand we don't have LESC so it's like shouting your + # keystrokes in the air + if not self.ble.connected or not self.hid.devices: + self.start_advertising() + + self.conn_id = 0 + + @property + def devices(self): + '''Search through the provided list of devices to find the ones with the + send_report attribute.''' + if not self.ble.connected: + return [] + + result = [] + # Security issue: + # This introduces a race condition. Let's say you have 2 active + # connections: Alice and Bob - Alice is connection 1 and Bob 2. + # Now Chuck who has already paired with the device in the past + # (this assumption is needed only in the case of LESC) + # wants to gather the keystrokes you send to Alice. You have + # selected right now to talk to Alice (1) and you're typing a secret. + # If Chuck kicks Alice off and is quick enough to connect to you, + # which means quicker than the running interval of this function, + # he'll be earlier in the `self.hid.devices` so will take over the + # selected 1 position in the resulted array. + # If no LESC is in place, Chuck can sniff the keystrokes anyway + for device in self.hid.devices: + if hasattr(device, 'send_report'): + result.append(device) + + return result + + def _check_connection(self): + devices = self.devices + if not devices: + return False + + if self.conn_id >= len(devices): + self.conn_id = len(devices) - 1 + + if self.conn_id < 0: + return False + + if not devices[self.conn_id]: + return False + + return True + + def hid_send(self, evt): + if not self._check_connection(): + return + + device = self.devices[self.conn_id] + + while len(evt) < len(device._characteristic.value) + 1: + evt.append(0) + + return device.send_report(evt[1:]) + + def clear_bonds(self): + import _bleio + + _bleio.adapter.erase_bonding() + + def next_connection(self): + self.conn_id = (self.conn_id + 1) % len(self.devices) + + def previous_connection(self): + self.conn_id = (self.conn_id - 1) % len(self.devices) + + def start_advertising(self): + advertisement = ProvideServicesAdvertisement(self.hid) + advertisement.appearance = self.BLE_APPEARANCE_HID_KEYBOARD + + self.ble.start_advertising(advertisement) + + def stop_advertising(self): + self.ble.stop_advertising() diff --git a/kmk/keys.py b/kmk/keys.py index 79c0d02..068c854 100644 --- a/kmk/keys.py +++ b/kmk/keys.py @@ -1,22 +1,20 @@ -import kmk.handlers.layers as layers -import kmk.handlers.modtap as modtap +from micropython import const + import kmk.handlers.stock as handlers from kmk.consts import UnicodeMode from kmk.key_validators import ( key_seq_sleep_validator, - layer_key_validator, - mod_tap_validator, tap_dance_key_validator, unicode_mode_key_validator, ) from kmk.types import AttrDict, UnicodeModeKeyMeta -FIRST_KMK_INTERNAL_KEY = 1000 +FIRST_KMK_INTERNAL_KEY = const(1000) NEXT_AVAILABLE_KEY = 1000 -KEY_SIMPLE = 0 -KEY_MODIFIER = 1 -KEY_CONSUMER = 2 +KEY_SIMPLE = const(0) +KEY_MODIFIER = const(1) +KEY_CONSUMER = const(2) # Global state, will be filled in througout this file, and # anywhere the user creates custom keys @@ -62,7 +60,7 @@ class Key: def __repr__(self): return 'Key(code={}, has_modifiers={})'.format(self.code, self.has_modifiers) - def _on_press(self, state, coord_int, coord_raw): + def on_press(self, state, coord_int, coord_raw): for fn in self._pre_press_handlers: if not fn(self, state, KC, coord_int, coord_raw): return None @@ -74,7 +72,7 @@ class Key: return ret - def _on_release(self, state, coord_int, coord_raw): + def on_release(self, state, coord_int, coord_raw): for fn in self._pre_release_handlers: if not fn(self, state, KC, coord_int, coord_raw): return None @@ -202,7 +200,7 @@ class ModifierKey(Key): # FIXME this is atrocious to read. Please, please, please, strike down upon # this with great vengeance and furious anger. - FAKE_CODE = -1 + FAKE_CODE = const(-1) def __call__(self, modified_code=None, no_press=None, no_release=None): if modified_code is None and no_press is None and no_release is None: @@ -610,66 +608,6 @@ make_key( on_press=handlers.gesc_pressed, on_release=handlers.gesc_released, ) -make_key(names=('RGB_TOG',), on_press=handlers.rgb_tog) -make_key(names=('RGB_HUI',), on_press=handlers.rgb_hui) -make_key(names=('RGB_HUD',), on_press=handlers.rgb_hud) -make_key(names=('RGB_SAI',), on_press=handlers.rgb_sai) -make_key(names=('RGB_SAD',), on_press=handlers.rgb_sad) -make_key(names=('RGB_VAI',), on_press=handlers.rgb_vai) -make_key(names=('RGB_VAD',), on_press=handlers.rgb_vad) -make_key(names=('RGB_ANI',), on_press=handlers.rgb_ani) -make_key(names=('RGB_AND',), on_press=handlers.rgb_and) -make_key(names=('RGB_MODE_PLAIN', 'RGB_M_P'), on_press=handlers.rgb_mode_static) -make_key(names=('RGB_MODE_BREATHE', 'RGB_M_B'), on_press=handlers.rgb_mode_breathe) -make_key(names=('RGB_MODE_RAINBOW', 'RGB_M_R'), on_press=handlers.rgb_mode_rainbow) -make_key( - names=('RGB_MODE_BREATHE_RAINBOW', 'RGB_M_BR'), - on_press=handlers.rgb_mode_breathe_rainbow, -) -make_key(names=('RGB_MODE_SWIRL', 'RGB_M_S'), on_press=handlers.rgb_mode_swirl) -make_key(names=('RGB_MODE_KNIGHT', 'RGB_M_K'), on_press=handlers.rgb_mode_knight) - -# Layers -make_argumented_key( - validator=layer_key_validator, - names=('MO',), - on_press=layers.mo_pressed, - on_release=layers.mo_released, -) -make_argumented_key( - validator=layer_key_validator, names=('DF',), on_press=layers.df_pressed -) -make_argumented_key( - validator=layer_key_validator, - names=('LM',), - on_press=layers.lm_pressed, - on_release=layers.lm_released, -) -make_argumented_key( - validator=layer_key_validator, - names=('LT',), - on_press=layers.lt_pressed, - on_release=layers.lt_released, -) -make_argumented_key( - validator=layer_key_validator, names=('TG',), on_press=layers.tg_pressed -) -make_argumented_key( - validator=layer_key_validator, names=('TO',), on_press=layers.to_pressed -) -make_argumented_key( - validator=layer_key_validator, - names=('TT',), - on_press=layers.tt_pressed, - on_release=layers.tt_released, -) - -make_argumented_key( - validator=mod_tap_validator, - names=('MT',), - on_press=modtap.mt_pressed, - on_release=modtap.mt_released, -) # A dummy key to trigger a sleep_ms call in a sequence of other keys in a # simple sequence macro. @@ -711,3 +649,4 @@ make_argumented_key( on_press=handlers.td_pressed, on_release=handlers.td_released, ) +make_key(names=('HID_SWITCH', 'HID'), on_press=handlers.hid_switch) diff --git a/kmk/kmk_keyboard.py b/kmk/kmk_keyboard.py index 2d47fc8..acb199c 100644 --- a/kmk/kmk_keyboard.py +++ b/kmk/kmk_keyboard.py @@ -1,11 +1,3 @@ -# There's a chance doing preload RAM hacks this late will cause recursion -# errors, but we'll see. I'd rather do it here than require everyone copy-paste -# a line into their keymaps. -import kmk.preload_imports # isort:skip # NOQA - -import gc - -from kmk import rgb from kmk.consts import KMK_RELEASE, UnicodeMode from kmk.hid import BLEHID, USBHID, AbstractHID, HIDModes from kmk.keys import KC @@ -14,62 +6,80 @@ from kmk.matrix import MatrixScanner, intify_coordinate from kmk.types import TapDanceKeyMeta +class Sandbox: + matrix_update = None + secondary_matrix_update = None + active_layers = None + + class KMKKeyboard: ##### # User-configurable debug_enabled = False - keymap = None + keymap = [] coord_mapping = None row_pins = None col_pins = None diode_orientation = None + matrix = None matrix_scanner = MatrixScanner uart_buffer = [] unicode_mode = UnicodeMode.NOOP tap_time = 300 - # RGB config - rgb_pixel_pin = None - rgb_config = rgb.rgb_config + modules = [] + extensions = [] + sandbox = Sandbox() ##### # Internal State - _keys_pressed = set() - _coord_keys_pressed = {} - _hid_pending = False + keys_pressed = set() + _coordkeys_pressed = {} + hid_type = HIDModes.USB + secondary_hid_type = None + _hid_helper = None + hid_pending = False + state_layer_key = None + matrix_update = None + secondary_matrix_update = None + _matrix_modify = None + state_changed = False + _old_timeouts_len = None + _new_timeouts_len = None + _trigger_powersave_enable = False + _trigger_powersave_disable = False + i2c_deinit_count = 0 # this should almost always be PREpended to, replaces # former use of reversed_active_layers which had pointless # overhead (the underlying list was never used anyway) - _active_layers = [0] + active_layers = [0] - _start_time = {'lt': None, 'tg': None, 'tt': None, 'lm': None} _timeouts = {} _tapping = False _tap_dance_counts = {} _tap_side_effects = {} + # on some M4 setups (such as klardotsh/klarank_feather_m4, CircuitPython + # 6.0rc1) this runs out of RAM every cycle and takes down the board. no + # real known fix yet other than turning off debug, but M4s have always been + # tight on RAM so.... def __repr__(self): return ( 'KMKKeyboard(' 'debug_enabled={} ' - 'keymap=truncated ' - 'coord_mapping=truncated ' - 'row_pins=truncated ' - 'col_pins=truncated ' 'diode_orientation={} ' 'matrix_scanner={} ' 'unicode_mode={} ' 'tap_time={} ' - 'hid_helper={} ' + '_hid_helper={} ' 'keys_pressed={} ' - 'coord_keys_pressed={} ' + 'coordkeys_pressed={} ' 'hid_pending={} ' 'active_layers={} ' - 'start_time={} ' 'timeouts={} ' 'tapping={} ' 'tap_dance_counts={} ' @@ -77,21 +87,16 @@ class KMKKeyboard: ')' ).format( self.debug_enabled, - # self.keymap, - # self.coord_mapping, - # self.row_pins, - # self.col_pins, self.diode_orientation, self.matrix_scanner, self.unicode_mode, self.tap_time, - self.hid_helper.__name__, + self._hid_helper, # internal state - self._keys_pressed, - self._coord_keys_pressed, - self._hid_pending, - self._active_layers, - self._start_time, + self.keys_pressed, + self._coordkeys_pressed, + self.hid_pending, + self.active_layers, self._timeouts, self._tapping, self._tap_dance_counts, @@ -99,126 +104,81 @@ class KMKKeyboard: ) def _print_debug_cycle(self, init=False): - pre_alloc = gc.mem_alloc() - pre_free = gc.mem_free() - if self.debug_enabled: if init: print('KMKInit(release={})'.format(KMK_RELEASE)) - print(self) - print(self) - print( - 'GCStats(pre_alloc={} pre_free={} alloc={} free={})'.format( - pre_alloc, pre_free, gc.mem_alloc(), gc.mem_free() - ) - ) def _send_hid(self): - self._hid_helper_inst.create_report(self._keys_pressed).send() - self._hid_pending = False + self._hid_helper.create_report(self.keys_pressed).send() + self.hid_pending = False def _handle_matrix_report(self, update=None): if update is not None: self._on_matrix_changed(update[0], update[1], update[2]) self.state_changed = True - def _receive_from_initiator(self): - if self.uart is not None and self.uart.in_waiting > 0 or self.uart_buffer: - if self.uart.in_waiting >= 60: - # This is a dirty hack to prevent crashes in unrealistic cases - import microcontroller - - microcontroller.reset() - - while self._uart.in_waiting >= 3: - self.uart_buffer.append(self._uart.read(3)) - if self.uart_buffer: - update = bytearray(self.uart_buffer.pop(0)) - - # Built in debug mode switch - if update == b'DEB': - print(self._uart.readline()) - return None - return update - - return None - - def _send_debug(self, message): - ''' - Prepends DEB and appends a newline to allow debug messages to - be detected and handled differently than typical keypresses. - :param message: Debug message - ''' - if self._uart is not None: - self._uart.write('DEB') - self._uart.write(message, '\n') - - ##### - # SPLICE: INTERNAL STATE - # FIXME CLEAN THIS - ##### - - def _find_key_in_map(self, row, col): - ic = intify_coordinate(row, col) - + def _find_key_in_map(self, int_coord, row, col): + self.state_layer_key = None try: - idx = self.coord_mapping.index(ic) + idx = self.coord_mapping.index(int_coord) except ValueError: if self.debug_enabled: print( - 'CoordMappingNotFound(ic={}, row={}, col={})'.format(ic, row, col) + 'CoordMappingNotFound(ic={}, row={}, col={})'.format( + int_coord, row, col + ) ) return None - for layer in self._active_layers: - layer_key = self.keymap[layer][idx] + for layer in self.active_layers: + self.state_layer_key = self.keymap[layer][idx] - if not layer_key or layer_key == KC.TRNS: + if not self.state_layer_key or self.state_layer_key == KC.TRNS: continue if self.debug_enabled: - print('KeyResolution(key={})'.format(layer_key)) + print('KeyResolution(key={})'.format(self.state_layer_key)) - return layer_key + return self.state_layer_key def _on_matrix_changed(self, row, col, is_pressed): if self.debug_enabled: print('MatrixChange(col={} row={} pressed={})'.format(col, row, is_pressed)) int_coord = intify_coordinate(row, col) - kc_changed = self._find_key_in_map(row, col) + kc_changed = self._find_key_in_map(int_coord, row, col) if kc_changed is None: print('MatrixUndefinedCoordinate(col={} row={})'.format(col, row)) return self - return self._process_key(kc_changed, is_pressed, int_coord, (row, col)) + return self.process_key(kc_changed, is_pressed, int_coord, (row, col)) - def _process_key(self, key, is_pressed, coord_int=None, coord_raw=None): + def process_key(self, key, is_pressed, coord_int=None, coord_raw=None): if self._tapping and not isinstance(key.meta, TapDanceKeyMeta): self._process_tap_dance(key, is_pressed) else: if is_pressed: - key._on_press(self, coord_int, coord_raw) + key.on_press(self, coord_int, coord_raw) else: - key._on_release(self, coord_int, coord_raw) + key.on_release(self, coord_int, coord_raw) return self - def _remove_key(self, keycode): - self._keys_pressed.discard(keycode) - return self._process_key(keycode, False) + def remove_key(self, keycode): + self.keys_pressed.discard(keycode) + return self.process_key(keycode, False) - def _add_key(self, keycode): - self._keys_pressed.add(keycode) - return self._process_key(keycode, True) + def add_key(self, keycode): + self.keys_pressed.add(keycode) + return self.process_key(keycode, True) - def _tap_key(self, keycode): - self._add_key(keycode) + def tap_key(self, keycode): + self.add_key(keycode) # On the next cycle, we'll remove the key. - self._set_timeout(False, lambda: self._remove_key(keycode)) + self.set_timeout(False, lambda: self.remove_key(keycode)) return self @@ -239,7 +199,7 @@ class KMKKeyboard: or not self._tap_dance_counts[changed_key] ): self._tap_dance_counts[changed_key] = 1 - self._set_timeout( + self.set_timeout( self.tap_time, lambda: self._end_tap_dance(changed_key) ) self._tapping = True @@ -263,19 +223,19 @@ class KMKKeyboard: v = self._tap_dance_counts[td_key] - 1 if v >= 0: - if td_key in self._keys_pressed: + if td_key in self.keys_pressed: key_to_press = td_key.codes[v] - self._add_key(key_to_press) + self.add_key(key_to_press) self._tap_side_effects[td_key] = key_to_press - self._hid_pending = True + self.hid_pending = True else: if self._tap_side_effects[td_key]: - self._remove_key(self._tap_side_effects[td_key]) + self.remove_key(self._tap_side_effects[td_key]) self._tap_side_effects[td_key] = None - self._hid_pending = True + self.hid_pending = True self._cleanup_tap_dance(td_key) else: - self._tap_key(td_key.codes[v]) + self.tap_key(td_key.codes[v]) self._cleanup_tap_dance(td_key) return self @@ -285,7 +245,7 @@ class KMKKeyboard: self._tapping = any(count > 0 for count in self._tap_dance_counts.values()) return self - def _set_timeout(self, after_ticks, callback): + def set_timeout(self, after_ticks, callback): if after_ticks is False: # We allow passing False as an implicit "run this on the next process timeouts cycle" timeout_key = ticks_ms() @@ -319,11 +279,6 @@ class KMKKeyboard: return self - ##### - # SPLICE END: INTERNAL STATE - # TODO FIXME REMOVE THIS - ##### - def _init_sanity_check(self): ''' Ensure the provided configuration is *probably* bootable @@ -347,9 +302,7 @@ class KMKKeyboard: To save RAM on boards that don't use Split, we don't import Split and do an isinstance check, but instead do string detection ''' - if any( - x.__class__.__module__ == 'kmk.extensions.split' for x in self._extensions - ): + if any(x.__class__.__module__ == 'kmk.modules.split' for x in self.modules): return if not self.coord_mapping: @@ -364,25 +317,14 @@ class KMKKeyboard: def _init_hid(self): if self.hid_type == HIDModes.NOOP: - self.hid_helper = AbstractHID + self._hid_helper = AbstractHID elif self.hid_type == HIDModes.USB: - try: - from kmk.hid import USBHID - - self.hid_helper = USBHID - except ImportError: - self.hid_helper = AbstractHID - print('USB HID is unsupported ') + self._hid_helper = USBHID elif self.hid_type == HIDModes.BLE: - try: - from kmk.ble import BLEHID - - self.hid_helper = BLEHID - except ImportError: - self.hid_helper = AbstractHID - print('Bluetooth is unsupported ') - - self._hid_helper_inst = self.hid_helper(**kwargs) + self._hid_helper = BLEHID + else: + self._hid_helper = AbstractHID + self._hid_helper = self._hid_helper() def _init_matrix(self): self.matrix = MatrixScanner( @@ -394,28 +336,115 @@ class KMKKeyboard: return self - def go(self, hid_type=HIDModes.USB, **kwargs): - self._extensions = [] + getattr(self, 'extensions', []) + def before_matrix_scan(self): + for module in self.modules: + try: + module.before_matrix_scan(self) + except Exception as err: + if self.debug_enabled: + print('Failed to run pre matrix function in module: ', err, module) - try: - del self.extensions - except Exception: - pass - finally: - gc.collect() + for ext in self.extensions: + try: + ext.before_matrix_scan(self.sandbox) + except Exception as err: + if self.debug_enabled: + print('Failed to run pre matrix function in extension: ', err, ext) + def after_matrix_scan(self): + for module in self.modules: + try: + module.after_matrix_scan(self) + except Exception as err: + if self.debug_enabled: + print('Failed to run post matrix function in module: ', err, module) + + for ext in self.extensions: + try: + ext.after_matrix_scan(self.sandbox) + except Exception as err: + if self.debug_enabled: + print('Failed to run post matrix function in extension: ', err, ext) + + def before_hid_send(self): + for module in self.modules: + try: + module.before_hid_send(self) + except Exception as err: + if self.debug_enabled: + print('Failed to run pre hid function in module: ', err, module) + + for ext in self.extensions: + try: + ext.before_hid_send(self.sandbox) + except Exception as err: + if self.debug_enabled: + print('Failed to run pre hid function in extension: ', err, ext) + + def after_hid_send(self): + for module in self.modules: + try: + module.after_hid_send(self) + except Exception as err: + if self.debug_enabled: + print('Failed to run post hid function in module: ', err, module) + + for ext in self.extensions: + try: + ext.after_hid_send(self.sandbox) + except Exception as err: + if self.debug_enabled: + print('Failed to run post hid function in extension: ', err, ext) + + def powersave_enable(self): + for module in self.modules: + try: + module.on_powersave_enable(self) + except Exception as err: + if self.debug_enabled: + print('Failed to run post hid function in module: ', err, module) + + for ext in self.extensions: + try: + ext.on_powersave_enable(self.sandbox) + except Exception as err: + if self.debug_enabled: + print('Failed to run post hid function in extension: ', err, ext) + + def powersave_disable(self): + for module in self.modules: + try: + module.on_powersave_disable(self) + except Exception as err: + if self.debug_enabled: + print('Failed to run post hid function in module: ', err, module) + for ext in self.extensions: + try: + ext.on_powersave_disable(self.sandbox) + except Exception as err: + if self.debug_enabled: + print('Failed to run post hid function in extension: ', err, ext) + + def go(self, hid_type=HIDModes.USB, secondary_hid_type=None, **kwargs): self.hid_type = hid_type + self.secondary_hid_type = secondary_hid_type self._init_sanity_check() self._init_coord_mapping() self._init_hid() - for ext in self._extensions: + for module in self.modules: + try: + module.during_bootup(self) + except Exception: + if self.debug_enabled: + print('Failed to load module', module) + for ext in self.extensions: try: ext.during_bootup(self) except Exception: - # TODO FIXME log the exceptions or something - pass + if self.debug_enabled: + print('Failed to load extention', ext) self._init_matrix() @@ -423,48 +452,43 @@ class KMKKeyboard: while True: self.state_changed = False + self.sandbox.active_layers = self.active_layers.copy() - for ext in self._extensions: - try: - self._handle_matrix_report(ext.before_matrix_scan(self)) - except Exception as e: - print(e) + self.before_matrix_scan() - matrix_update = self.matrix.scan_for_changes() - self._handle_matrix_report(matrix_update) + self.matrix_update = ( + self.sandbox.matrix_update + ) = self.matrix.scan_for_changes() + self.sandbox.secondary_matrix_update = self.secondary_matrix_update - for ext in self._extensions: - try: - ext.after_matrix_scan(self, matrix_update) - except Exception as e: - print(e) + self.after_matrix_scan() - for ext in self._extensions: - try: - ext.before_hid_send(self) - except Exception: - # TODO FIXME log the exceptions or something - pass + self._handle_matrix_report(self.secondary_matrix_update) + self.secondary_matrix_update = None + self._handle_matrix_report(self.matrix_update) + self.matrix_update = None - if self._hid_pending: + self.before_hid_send() + + if self.hid_pending: self._send_hid() - old_timeouts_len = len(self._timeouts) + self._old_timeouts_len = len(self._timeouts) self._process_timeouts() - new_timeouts_len = len(self._timeouts) + self._new_timeouts_len = len(self._timeouts) - if old_timeouts_len != new_timeouts_len: + if self._old_timeouts_len != self._new_timeouts_len: self.state_changed = True - - if self._hid_pending: + if self.hid_pending: self._send_hid() - for ext in self._extensions: - try: - ext.after_hid_send(self) - except Exception: - # TODO FIXME log the exceptions or something - pass + self.after_hid_send() + + if self._trigger_powersave_enable: + self.powersave_enable() + + if self._trigger_powersave_disable: + self.powersave_disable() if self.state_changed: self._print_debug_cycle() diff --git a/kmk/kmktime.py b/kmk/kmktime.py index 39381c8..18b62a8 100644 --- a/kmk/kmktime.py +++ b/kmk/kmktime.py @@ -1,29 +1,23 @@ -import math import time -USE_UTIME = False - def sleep_ms(ms): - ''' - Tries to sleep for a number of milliseconds in a cross-implementation - way. Will raise an ImportError if time is not available on the platform. - ''' - if USE_UTIME: - return time.sleep_ms(ms) - else: - return time.sleep(ms / 1000) + return time.sleep(ms / 1000) def ticks_ms(): - if USE_UTIME: - return time.ticks_ms() - else: - return math.floor(time.monotonic() * 1000) + '''Has .25s granularity, but is cheap''' + return time.monotonic() * 1000 def ticks_diff(new, old): - if USE_UTIME: - return time.ticks_diff(new, old) - else: - return new - old + return new - old + + +def accurate_ticks(): + '''Is more expensive, but good for time critical things''' + return time.monotonic_ns() + + +def accurate_ticks_diff(new, old, ms): + return bool(new - old < ms * 1000000) diff --git a/kmk/modules/__init__.py b/kmk/modules/__init__.py new file mode 100644 index 0000000..e78b6c9 --- /dev/null +++ b/kmk/modules/__init__.py @@ -0,0 +1,40 @@ +class InvalidExtensionEnvironment(Exception): + pass + + +class Module: + ''' + Modules differ from extensions in that they not only can read the state, but + are allowed to modify the state. The will be loaded on boot, and are not + allowed to be unloaded as they are required to continue functioning in a + consistant manner. + ''' + + # The below methods should be implemented by subclasses + + def during_bootup(self, keyboard): + raise NotImplementedError + + def before_matrix_scan(self, keyboard): + ''' + Return value will be injected as an extra matrix update + ''' + raise NotImplementedError + + def after_matrix_scan(self, keyboard): + ''' + Return value will be replace matrix update if supplied + ''' + raise NotImplementedError + + def before_hid_send(self, keyboard): + raise NotImplementedError + + def after_hid_send(self, keyboard): + raise NotImplementedError + + def on_powersave_enable(self, keyboard): + raise NotImplementedError + + def on_powersave_disable(self, keyboard): + raise NotImplementedError diff --git a/kmk/modules/layers.py b/kmk/modules/layers.py new file mode 100644 index 0000000..416bc27 --- /dev/null +++ b/kmk/modules/layers.py @@ -0,0 +1,191 @@ +'''One layer isn't enough. Adds keys to get to more of them''' +from micropython import const + +from kmk.key_validators import layer_key_validator +from kmk.keys import make_argumented_key +from kmk.kmktime import accurate_ticks, accurate_ticks_diff +from kmk.modules import Module + + +class LayerType: + '''Defines layer type values for readability''' + + MO = const(0) + DF = const(1) + LM = const(2) + LT = const(3) + TG = const(4) + TT = const(5) + + +class Layers(Module): + '''Gives access to the keys used to enable the layer system''' + + def __init__(self): + # Layers + self.start_time = { + LayerType.LT: None, + LayerType.TG: None, + LayerType.TT: None, + LayerType.LM: None, + } + make_argumented_key( + validator=layer_key_validator, + names=('MO',), + on_press=self._mo_pressed, + on_release=self._mo_released, + ) + make_argumented_key( + validator=layer_key_validator, names=('DF',), on_press=self._df_pressed + ) + make_argumented_key( + validator=layer_key_validator, + names=('LM',), + on_press=self._lm_pressed, + on_release=self._lm_released, + ) + make_argumented_key( + validator=layer_key_validator, + names=('LT',), + on_press=self._lt_pressed, + on_release=self._lt_released, + ) + make_argumented_key( + validator=layer_key_validator, names=('TG',), on_press=self._tg_pressed + ) + make_argumented_key( + validator=layer_key_validator, names=('TO',), on_press=self._to_pressed + ) + make_argumented_key( + validator=layer_key_validator, + names=('TT',), + on_press=self._tt_pressed, + on_release=self._tt_released, + ) + + def during_bootup(self, keyboard): + return + + def before_matrix_scan(self, keyboard): + return + + def after_matrix_scan(self, keyboard): + return + + def before_hid_send(self, keyboard): + return + + def after_hid_send(self, keyboard): + return + + def on_powersave_enable(self, keyboard): + return + + def on_powersave_disable(self, keyboard): + return + + def _df_pressed(self, key, keyboard, *args, **kwargs): + ''' + Switches the default layer + ''' + keyboard.active_layers[-1] = key.meta.layer + + def _mo_pressed(self, key, keyboard, *args, **kwargs): + ''' + Momentarily activates layer, switches off when you let go + ''' + keyboard.active_layers.insert(0, key.meta.layer) + + @staticmethod + def _mo_released(key, keyboard, *args, **kwargs): + # remove the first instance of the target layer + # from the active list + # under almost all normal use cases, this will + # disable the layer (but preserve it if it was triggered + # as a default layer, etc.) + # this also resolves an issue where using DF() on a layer + # triggered by MO() and then defaulting to the MO()'s layer + # would result in no layers active + try: + del_idx = keyboard.active_layers.index(key.meta.layer) + del keyboard.active_layers[del_idx] + except ValueError: + pass + + def _lm_pressed(self, key, keyboard, *args, **kwargs): + ''' + As MO(layer) but with mod active + ''' + keyboard.hid_pending = True + # Sets the timer start and acts like MO otherwise + 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.hid_pending = True + keyboard.keys_pressed.discard(key.meta.kc) + self._mo_released(key, keyboard, *args, **kwargs) + + def _lt_pressed(self, key, keyboard, *args, **kwargs): + # Sets the timer start and acts like MO otherwise + self.start_time[LayerType.LT] = accurate_ticks() + self._mo_pressed(key, keyboard, *args, **kwargs) + + def _lt_released(self, key, keyboard, *args, **kwargs): + # On keyup, check timer, and press key if needed. + if self.start_time[LayerType.LT] and ( + accurate_ticks_diff( + accurate_ticks(), self.start_time[LayerType.LT], keyboard.tap_time + ) + ): + keyboard.hid_pending = True + keyboard.tap_key(key.meta.kc) + + self._mo_released(key, keyboard, *args, **kwargs) + self.start_time[LayerType.LT] = None + + def _tg_pressed(self, key, keyboard, *args, **kwargs): + ''' + Toggles the layer (enables it if not active, and vise versa) + ''' + # See mo_released for implementation details around this + try: + del_idx = keyboard.active_layers.index(key.meta.layer) + del keyboard.active_layers[del_idx] + except ValueError: + keyboard.active_layers.insert(0, key.meta.layer) + + def _to_pressed(self, key, keyboard, *args, **kwargs): + ''' + Activates layer and deactivates all other layers + ''' + keyboard.active_layers.clear() + keyboard.active_layers.insert(0, key.meta.layer) + + def _tt_pressed(self, key, keyboard, *args, **kwargs): + ''' + Momentarily activates layer if held, toggles it if tapped repeatedly + ''' + if self.start_time[LayerType.TT] is None: + # Sets the timer start and acts like MO otherwise + self.start_time[LayerType.TT] = accurate_ticks() + self._mo_pressed(key, keyboard, *args, **kwargs) + elif accurate_ticks_diff( + accurate_ticks(), self.start_time[LayerType.TT], keyboard.tap_time + ): + self.start_time[LayerType.TT] = None + self._tg_pressed(key, keyboard, *args, **kwargs) + return + return + + def _tt_released(self, key, keyboard, *args, **kwargs): + if self.start_time[LayerType.TT] is None or not accurate_ticks_diff( + accurate_ticks(), self.start_time[LayerType.TT], keyboard.tap_time + ): + # On first press, works like MO. On second press, does nothing unless let up within + # time window, then acts like TG. + self.start_time[LayerType.TT] = None + self._mo_released(key, keyboard, *args, **kwargs) diff --git a/kmk/modules/modtap.py b/kmk/modules/modtap.py new file mode 100644 index 0000000..ef0ac55 --- /dev/null +++ b/kmk/modules/modtap.py @@ -0,0 +1,57 @@ +from kmk.key_validators import mod_tap_validator +from kmk.keys import make_argumented_key +from kmk.kmktime import accurate_ticks, accurate_ticks_diff +from kmk.modules import Module + + +class ModTap(Module): + def __init__(self): + self._mod_tap_timer = None + make_argumented_key( + validator=mod_tap_validator, + names=('MT',), + on_press=self.mt_pressed, + on_release=self.mt_released, + ) + + def during_bootup(self, keyboard): + return + + def before_matrix_scan(self, keyboard): + return + + def after_matrix_scan(self, keyboard): + return + + def before_hid_send(self, keyboard): + return + + def after_hid_send(self, keyboard): + return + + def on_powersave_enable(self, keyboard): + return + + def on_powersave_disable(self, keyboard): + return + + def mt_pressed(self, key, keyboard, *args, **kwargs): + '''Sets the timer start and acts like a modifier otherwise''' + keyboard.keys_pressed.add(key.meta.mods) + + self._mod_tap_timer = accurate_ticks() + return keyboard + + def mt_released(self, key, keyboard, *args, **kwargs): + ''' On keyup, check timer, and press key if needed.''' + keyboard.keys_pressed.discard(key.meta.mods) + if self._mod_tap_timer and ( + accurate_ticks_diff( + accurate_ticks(), self._mod_tap_timer, keyboard.tap_time + ) + ): + keyboard.hid_pending = True + keyboard.tap_key(key.meta.kc) + + self._mod_tap_timer = None + return keyboard diff --git a/kmk/modules/power.py b/kmk/modules/power.py new file mode 100644 index 0000000..d25845b --- /dev/null +++ b/kmk/modules/power.py @@ -0,0 +1,146 @@ +import board +import digitalio + +from kmk.handlers.stock import passthrough as handler_passthrough +from kmk.keys import make_key +from kmk.kmktime import sleep_ms, ticks_diff, ticks_ms +from kmk.modules import Module + + +class Power(Module): + def __init__(self, powersave_pin=None): + self.enable = False + self.powersave_pin = powersave_pin # Powersave pin board object + self._powersave_start = ticks_ms() + self._usb_last_scan = ticks_ms() - 5000 + self._psp = None # Powersave pin object + self._i2c = 0 + self._loopcounter = 0 + + make_key( + names=('PS_TOG',), on_press=self._ps_tog, on_release=handler_passthrough + ) + make_key( + names=('PS_ON',), on_press=self._ps_enable, on_release=handler_passthrough + ) + make_key( + names=('PS_OFF',), on_press=self._ps_disable, on_release=handler_passthrough + ) + + def __repr__(self): + return f'Power({self._to_dict()})' + + def _to_dict(self): + return { + 'enable': self.enable, + 'powersave_pin': self.powersave_pin, + '_powersave_start': self._powersave_start, + '_usb_last_scan': self._usb_last_scan, + '_psp': self._psp, + } + + def during_bootup(self, keyboard): + self._i2c_scan() + + def before_matrix_scan(self, keyboard): + return + + def after_matrix_scan(self, keyboard): + if keyboard.matrix_update or keyboard.secondary_matrix_update: + self.psave_time_reset() + + def before_hid_send(self, keyboard): + return + + def after_hid_send(self, keyboard): + if self.enable: + self.psleep() + + def on_powersave_enable(self, keyboard): + '''Gives 10 cycles to allow other extentions to clean up before powersave''' + if self._loopcounter > 10: + self.enable_powersave(keyboard) + self._loopcounter = 0 + else: + self._loopcounter += 1 + return + + def on_powersave_disable(self, keyboard): + self.disable_powersave(keyboard) + return + + def enable_powersave(self, keyboard): + '''Enables power saving features''' + if keyboard.i2c_deinit_count >= self._i2c and self.powersave_pin: + # Allows power save to prevent RGB drain. + # Example here https://docs.nicekeyboards.com/#/nice!nano/pinout_schematic + + if not self._psp: + self._psp = digitalio.DigitalInOut(self.powersave_pin) + self._psp.direction = digitalio.Direction.OUTPUT + if self._psp: + self._psp.value = True + + self.enable = True + keyboard._trigger_powersave_enable = False + return + + def disable_powersave(self, keyboard): + '''Disables power saving features''' + if self._psp: + self._psp.value = False + # Allows power save to prevent RGB drain. + # Example here https://docs.nicekeyboards.com/#/nice!nano/pinout_schematic + + keyboard._trigger_powersave_disable = False + self.enable = False + return + + def psleep(self): + ''' + Sleeps longer and longer to save power the more time in between updates. + ''' + if ticks_diff(ticks_ms(), self._powersave_start) <= 60000: + sleep_ms(8) + elif ticks_diff(ticks_ms(), self._powersave_start) >= 240000: + sleep_ms(180) + return + + def psave_time_reset(self): + self._powersave_start = ticks_ms() + + def _i2c_scan(self): + i2c = board.I2C() + while not i2c.try_lock(): + pass + try: + self._i2c = len(i2c.scan()) + finally: + i2c.unlock() + return + + def usb_rescan_timer(self): + return bool(ticks_diff(ticks_ms(), self._usb_last_scan) > 5000) + + def usb_time_reset(self): + self._usb_last_scan = ticks_ms() + return + + def usb_scan(self): + # TODO Add USB detection here. Currently lies that it's connected + # https://github.com/adafruit/circuitpython/pull/3513 + return True + + def _ps_tog(self, key, keyboard, *args, **kwargs): + if self.enable: + keyboard._trigger_powersave_disable = True + else: + keyboard._trigger_powersave_enable = True + + def _ps_enable(self, key, keyboard, *args, **kwargs): + if not self.enable: + keyboard._trigger_powersave_enable = True + + def _ps_disable(self, key, keyboard, *args, **kwargs): + if self.enable: + keyboard._trigger_powersave_disable = True diff --git a/kmk/modules/split.py b/kmk/modules/split.py new file mode 100644 index 0000000..976188a --- /dev/null +++ b/kmk/modules/split.py @@ -0,0 +1,308 @@ +'''Enables splitting keyboards wirelessly or wired''' +import busio +from micropython import const + +from kmk.hid import HIDModes +from kmk.kmktime import ticks_diff, ticks_ms +from kmk.matrix import intify_coordinate +from kmk.modules import Module +from storage import getmount + + +class SplitSide: + LEFT = const(1) + RIGHT = const(2) + + +class SplitType: + UART = const(1) + I2C = const(2) # unused + ONEWIRE = const(3) # unused + BLE = const(4) + + +class Split(Module): + '''Enables splitting keyboards wirelessly, or wired''' + + def __init__( + self, + split_flip=True, + split_side=None, + split_type=SplitType.UART, + split_target_left=True, + uart_interval=20, + data_pin=None, + data_pin2=None, + target_left=True, + uart_flip=True, + ): + self._is_target = True + self._uart_buffer = [] + self.split_flip = split_flip + self.split_side = split_side + self.split_type = split_type + self.split_target_left = split_target_left + self.split_offset = None + self.data_pin = data_pin + self.data_pin2 = data_pin2 + self.target_left = target_left + self.uart_flip = uart_flip + self._is_target = True + self._uart = None + self._uart_interval = uart_interval + self._debug_enabled = False + if self.split_type == SplitType.BLE: + try: + from adafruit_ble import BLERadio + from adafruit_ble.advertising.standard import ( + ProvideServicesAdvertisement, + ) + from adafruit_ble.services.nordic import UARTService + + self.ProvideServicesAdvertisement = ProvideServicesAdvertisement + self.UARTService = UARTService + except ImportError: + pass # BLE isn't supported on this platform + self._ble = BLERadio() + self._ble_last_scan = ticks_ms() - 5000 + self._connection_count = 0 + self._uart_connection = None + self._advertisment = None + self._advertising = False + self._psave_enable = False + + def __repr__(self): + return f'BLE_SPLIT({self._to_dict()})' + + def _to_dict(self): + return { + '_ble': self._ble, + '_ble_last_scan': self._ble_last_scan, + '_is_target': self._is_target, + 'uart_buffer': self._uart_buffer, + '_split_flip': self.split_flip, + '_split_side': self.split_side, + } + + def during_bootup(self, keyboard): + # Set up name for target side detection and BLE advertisment + name = str(getmount('/').label) + if self.split_type == SplitType.BLE: + self._ble.name = name + else: + # Try to guess data pins if not supplied + if not self.data_pin: + self.data_pin = keyboard.data_pin + + # Detect split side from name + if self.split_side is None: + if name.endswith('L'): + # If name ends in 'L' assume left and strip from name + self._is_target = bool(self.split_target_left) + self.split_side = SplitSide.LEFT + elif name.endswith('R'): + # If name ends in 'R' assume right and strip from name + self._is_target = not bool(self.split_target_left) + self.split_side = SplitSide.RIGHT + + # if split side was given, find master from split_side. + elif self.split_side == SplitSide.LEFT: + self._is_target = bool(self.split_target_left) + elif self.split_side == SplitSide.RIGHT: + self._is_target = not bool(self.split_target_left) + + # Flips the col pins if PCB is the same but flipped on right + if self.split_flip and self.split_side == SplitSide.RIGHT: + keyboard.col_pins = list(reversed(keyboard.col_pins)) + + self.split_offset = len(keyboard.col_pins) + + if self.split_type == SplitType.UART and self.data_pin is not None: + if self._is_target: + self._uart = busio.UART( + tx=self.data_pin2, rx=self.data_pin, timeout=self._uart_interval + ) + else: + self._uart = busio.UART( + tx=self.data_pin, rx=self.data_pin2, timeout=self._uart_interval + ) + + # Attempt to sanely guess a coord_mapping if one is not provided. + if not keyboard.coord_mapping: + keyboard.coord_mapping = [] + + rows_to_calc = len(keyboard.row_pins) * 2 + cols_to_calc = len(keyboard.col_pins) * 2 + + for ridx in range(rows_to_calc): + for cidx in range(cols_to_calc): + keyboard.coord_mapping.append(intify_coordinate(ridx, cidx)) + + def before_matrix_scan(self, keyboard): + if self.split_type == SplitType.BLE: + self._check_all_connections(keyboard._hid_helper) + self._receive_ble(keyboard) + elif self.split_type == SplitType.UART: + if self._is_target or self.data_pin2: + self._receive_uart(keyboard) + elif self.split_type == SplitType.ONEWIRE: + pass # Protocol needs written + return + + def after_matrix_scan(self, keyboard): + if keyboard.matrix_update: + if self.split_type == SplitType.BLE: + self._send_ble(keyboard.matrix_update) + elif self.split_type == SplitType.UART and self.data_pin2: + self._send_uart(keyboard.matrix_update) + elif self.split_type == SplitType.ONEWIRE: + pass # Protocol needs written + + return + + def before_hid_send(self, keyboard): + return + + def after_hid_send(self, keyboard): + return + + def on_powersave_enable(self, keyboard): + if self.split_type == SplitType.BLE: + if self._uart_connection and not self._psave_enable: + self._uart_connection.connection_interval = self._uart_interval + self._psave_enable = True + + def on_powersave_disable(self, keyboard): + if self.split_type == SplitType.BLE: + if self._uart_connection and self._psave_enable: + self._uart_connection.connection_interval = 11.25 + self._psave_enable = False + + def _check_all_connections(self, hid_type): + '''Validates the correct number of BLE connections''' + self._connection_count = len(self._ble.connections) + if self._is_target and hid_type == HIDModes.BLE and self._connection_count < 2: + self._target_advertise() + elif not self._is_target and self._connection_count < 1: + self._initiator_scan() + + def _initiator_scan(self): + '''Scans for target device''' + self._uart = None + self._uart_connection = None + # See if any existing connections are providing UARTService. + self._connection_count = len(self._ble.connections) + if self._connection_count > 0 and not self._uart: + for connection in self._ble.connections: + if self.UARTService in connection: + self._uart_connection = connection + self._uart_connection.connection_interval = 11.25 + self._uart = self._uart_connection[self.UARTService] + break + + if not self._uart: + if self._debug_enabled: + print('Scanning') + self._ble.stop_scan() + for adv in self._ble.start_scan( + self.ProvideServicesAdvertisement, timeout=20 + ): + if self._debug_enabled: + print('Scanning') + if self.UARTService in adv.services and adv.rssi > -70: + self._uart_connection = self._ble.connect(adv) + self._uart_connection.connection_interval = 11.25 + self._uart = self._uart_connection[self.UARTService] + self._ble.stop_scan() + if self._debug_enabled: + print('Scan complete') + break + self._ble.stop_scan() + + def _target_advertise(self): + '''Advertises the target for the initiator to find''' + self._ble.stop_advertising() + if self._debug_enabled: + print('Advertising') + # Uart must not change on this connection if reconnecting + if not self._uart: + self._uart = self.UARTService() + advertisement = self.ProvideServicesAdvertisement(self._uart) + + self._ble.start_advertising(advertisement) + + self.ble_time_reset() + while not self.ble_rescan_timer(): + self._connection_count = len(self._ble.connections) + if self._connection_count > 1: + self.ble_time_reset() + if self._debug_enabled: + print('Advertising complete') + break + self._ble.stop_advertising() + + def ble_rescan_timer(self): + '''If true, the rescan timer is up''' + return bool(ticks_diff(ticks_ms(), self._ble_last_scan) > 5000) + + def ble_time_reset(self): + '''Resets the rescan timer''' + self._ble_last_scan = ticks_ms() + + def _send_ble(self, update): + if self._uart: + try: + if not self._is_target: + update[1] += self.split_offset + self._uart.write(update) + except OSError: + try: + self._uart.disconnect() + except: # noqa: E722 + if self._debug_enabled: + print('UART disconnect failed') + + if self._debug_enabled: + print('Connection error') + self._uart_connection = None + self._uart = None + + def _receive_ble(self, keyboard): + if self._uart is not None and self._uart.in_waiting > 0 or self._uart_buffer: + while self._uart.in_waiting >= 3: + self._uart_buffer.append(self._uart.read(3)) + if self._uart_buffer: + keyboard.secondary_matrix_update = bytearray(self._uart_buffer.pop(0)) + return + + def _send_uart(self, update): + # Change offsets depending on where the data is going to match the correct + # matrix location of the receiever + if self._is_target: + if self.split_target_left: + update[1] += self.split_offset + else: + update[1] -= self.split_offset + else: + if self.split_target_left: + update[1] -= self.split_offset + else: + update[1] += self.split_offset + + if self._uart is not None: + self._uart.write(update) + + def _receive_uart(self, keyboard): + if self._uart is not None and self._uart.in_waiting > 0 or self._uart_buffer: + if self._uart.in_waiting >= 60: + # This is a dirty hack to prevent crashes in unrealistic cases + import microcontroller + + microcontroller.reset() + + while self._uart.in_waiting >= 3: + self._uart_buffer.append(self._uart.read(3)) + if self._uart_buffer: + keyboard.secondary_matrix_update = bytearray(self._uart_buffer.pop(0)) + + return diff --git a/kmk/preload_imports.py b/kmk/preload_imports.py deleted file mode 100644 index f6f5f26..0000000 --- a/kmk/preload_imports.py +++ /dev/null @@ -1,37 +0,0 @@ -# Welcome to RAM and stack size hacks central, I'm your host, klardotsh! -# Our import structure is deeply nested enough that stuff -# breaks in some truly bizarre ways, including: -# - explicit RuntimeError exceptions, complaining that our -# stack depth is too deep -# -# - silent hard locks of the device (basically unrecoverable without -# UF2 flash if done in main.py, fixable with a reboot if done -# in REPL) -# -# However, there's a hackaround that works for us! Because sys.modules -# caches everything it sees (and future imports will use that cached -# copy of the module), let's take this opportunity _way_ up the import -# chain to import _every single thing_ KMK eventually uses in a normal -# workflow, in nesting order -# -# GC runs automatically after CircuitPython imports. - -# First, system-provided deps -import busio -import collections -import gc -import supervisor - -# Now "light" KMK stuff with few/no external deps -import kmk.consts # isort:skip -import kmk.kmktime # isort:skip -import kmk.types # isort:skip - -# Now handlers that will be used in keys later -import kmk.handlers.layers # isort:skip -import kmk.handlers.stock # isort:skip - -# Now stuff that depends on the above (and so on) -import kmk.hid # isort:skip -import kmk.keys # isort:skip -import kmk.matrix # isort:skip diff --git a/pyproject.toml b/pyproject.toml index b705225..859393f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,6 +15,7 @@ exclude = ''' | \.pytest_cache | \.compiled | dist + | boards | build | docs | user_keymaps diff --git a/setup.cfg b/setup.cfg index 786ea94..aace96d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -22,9 +22,8 @@ per-file-ignores = # multiple spaces after commas in lists (for grid alignment), and put # 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 tests/test_data/keymaps/**/*.py: F401,E501 -# Forgive me for my RAM hack sins - kmk/preload_imports.py: I001,I003,I004,F401 [isort] known_standard_library = diff --git a/user_keymaps/default/__init__.py b/user_keymaps/default/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/user_keymaps/default/converter/__init__.py b/user_keymaps/default/converter/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/user_keymaps/default/converter/fourtypercentclub/__init__.py b/user_keymaps/default/converter/fourtypercentclub/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/user_keymaps/default/converter/keebio/__init__.py b/user_keymaps/default/converter/keebio/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/user_keymaps/default/nice_nano/__init__.py b/user_keymaps/default/nice_nano/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/user_keymaps/default/nice_nano/crkbd.py b/user_keymaps/default/nice_nano/crkbd.py deleted file mode 100644 index 4fa2b6d..0000000 --- a/user_keymaps/default/nice_nano/crkbd.py +++ /dev/null @@ -1,41 +0,0 @@ -from kmk.boards.nice_nano.crkbd import KMKKeyboard -from kmk.keys import KC - -keyboard = KMKKeyboard() - -_______ = KC.TRNS -XXXXXXX = KC.NO - -LOWER = KC.MO(3) -RAISE = KC.MO(4) -ADJUST = KC.MO(5) - -keyboard.keymap = [ - [ #QWERTY - KC.TAB, KC.Q, KC.W, KC.E, KC.R, KC.T, KC.Y, KC.U, KC.I, KC.O, KC.P, KC.BSPC,\ - KC.LCTL, KC.A, KC.S, KC.D, KC.F, KC.G, KC.H, KC.J, KC.K, KC.L, KC.SCLN, KC.QUOT,\ - KC.LSFT, KC.Z, KC.X, KC.C, KC.V, KC.B, KC.N, KC.M, KC.COMM, KC.DOT, KC.SLSH, KC.RSFT,\ - KC.LGUI, LOWER, KC.SPC, KC.ENT, RAISE, KC.RALT, - ], - [ #LOWER - KC.ESC, KC.N1, KC.N2, KC.N3, KC.N4, KC.N5, KC.N6, KC.N7, KC.N8, KC.N9, KC.N0, KC.BSPC,\ - KC.LCTL, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC.LEFT, KC.DOWN, KC.UP, KC.RIGHT, XXXXXXX, XXXXXXX,\ - KC.LSFT, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,\ - KC.LGUI, LOWER, KC.SPC, KC.ENT, RAISE, KC.RALT, - ], - [ #RAISE - KC.ESC, KC.EXLM, KC.AT, KC.HASH, KC.DLR, KC.PERC, KC.CIRC, KC.AMPR, KC.ASTR, KC.LPRN, KC.RPRN, KC.BSPC,\ - KC.LCTL, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC.MINS, KC.EQL, KC.LCBR, KC.RCBR, KC.PIPE, KC.GRV,\ - KC.LSFT, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC.UNDS, KC.PLUS, KC.LBRC, KC.RBRC, KC.BSLS, KC.TILD,\ - KC.LGUI, LOWER, KC.SPC, KC.ENT, RAISE, KC.RALT, - ], - [ #ADJUST - XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,\ - XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,\ - XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,\ - KC.LGUI, LOWER, KC.SPC, KC.ENT, RAISE, KC.RALT, - ] -] - -if __name__ == '__main__': - keyboard.go() diff --git a/user_keymaps/dzervas/lab68.py b/user_keymaps/dzervas/lab68.py index 7d1e05c..537e5d3 100644 --- a/user_keymaps/dzervas/lab68.py +++ b/user_keymaps/dzervas/lab68.py @@ -7,12 +7,15 @@ from kmk.hid import HIDModes from kmk.keys import KC from kmk.kmk_keyboard import KMKKeyboard from kmk.matrix import DiodeOrientation +from kmk.modules.layers import Layers # DEBUG_ENABLE = True i2c = busio.I2C(scl=board.SCL, sda=board.SDA, frequency=100000) mcp = MCP23017(i2c, address=0x20) keyboard = KMKKeyboard() +layer_ext = Layers +keyboard.modules = [layer_ext] _______ = KC.TRNS XXXXXXX = KC.NO diff --git a/user_keymaps/kdb424/corne.py b/user_keymaps/kdb424/corne.py index be3ffa1..185bc26 100644 --- a/user_keymaps/kdb424/corne.py +++ b/user_keymaps/kdb424/corne.py @@ -1,37 +1,54 @@ -import gc +# OLED +import board -from kmk.boards.nice_nano.crkbd import KMKKeyboard +import adafruit_displayio_ssd1306 +import displayio +import terminalio +from adafruit_display_text import label +from kb import KMKKeyboard +from kmk.extensions.rgb import RGB from kmk.hid import HIDModes from kmk.keys import KC +from kmk.modules.layers import Layers +from kmk.modules.power import Power +from kmk.modules.split import Split, SplitType keyboard = KMKKeyboard() + +keyboard.tap_time = 320 +keyboard.debug_enabled = False + +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(split_type=SplitType.BLE) +power = Power(powersave_pin=keyboard.powersave_pin) +layers = Layers() + +keyboard.modules = [split, power, layers] +keyboard.extensions = [rgb_ext] + +enable_oled = False + +if enable_oled: + displayio.release_displays() + i2c = board.I2C() + display_bus = displayio.I2CDisplay(i2c, device_address=0x3c) + display = adafruit_displayio_ssd1306.SSD1306(display_bus, width=128, height=32) + splash = displayio.Group(max_size=10) + display.show(splash) +else: + displayio.release_displays() + keyboard.i2c_deinit_count += 1 + _______ = KC.TRNS XXXXXXX = KC.NO -LT1_SP = KC.LT(2, KC.SPC) +LT1_SP = KC.MO(2) LT2_SP = KC.LT(3, KC.SPC) TAB_SB = KC.LT(5, KC.TAB) SUPER_L = KC.LM(4, KC.LGUI) -keyboard.tap_time = 150 -keyboard.leader_timeout = 2000 -keyboard.debug_enabled = False - -# RGB Config (underglow) -keyboard.rgb_config['num_pixels'] = 27 -keyboard.rgb_config['val_limit'] = 150 -keyboard.rgb_config['hue_step'] = 10 -keyboard.rgb_config['sat_step'] = 5 -keyboard.rgb_config['val_step'] = 5 -keyboard.rgb_config['hue_default'] = 260 -keyboard.rgb_config['sat_default'] = 100 -keyboard.rgb_config['val_default'] = 40 -keyboard.rgb_config['knight_effect_length'] = 4 -keyboard.rgb_config['animation_mode'] = 'static' -keyboard.rgb_config['animation_speed'] = 1 - - keyboard.keymap = [ # DVORAK # ,-----------------------------------------. ,-----------------------------------------. @@ -50,7 +67,7 @@ keyboard.keymap = [ KC.GESC, KC.QUOT, KC.COMM, KC.DOT, KC.P, KC.Y, KC.F, KC.G, KC.C, KC.R, KC.L, KC.BSPC, \ TAB_SB, KC.A, KC.O, KC.E, KC.U, KC.I, KC.D, KC.H, KC.T, KC.N, KC.S, KC.ENT, \ KC.LSFT, KC.SCLN, KC.Q, KC.J, KC.K, KC.X, KC.B, KC.M, KC.W, KC.V, KC.Z, KC.SLSH, \ - KC.LALT, SUPER_L, LT1_SP, LT2_SP, KC.LCTL, KC.LEAD, + KC.LALT, SUPER_L, LT1_SP, LT2_SP, KC.LCTL, KC.N0 ], # GAMING @@ -86,7 +103,7 @@ keyboard.keymap = [ # [ # RAISE1 - _______, _______, _______, _______, _______, _______, XXXXXXX, XXXXXXX, KC.N7, KC.N8, KC.N9, KC.DEL, \ + _______, _______, _______, _______, _______, _______, KC.PS_TOG, XXXXXXX, KC.N7, KC.N8, KC.N9, KC.DEL, \ _______, _______, _______, _______, _______, _______, XXXXXXX, XXXXXXX, KC.N4, KC.N5, KC.N6, KC.BSLS, \ _______, _______, _______, _______, _______, _______, XXXXXXX, XXXXXXX, KC.N1, KC.N2, KC.N3, KC.MINS, \ _______, _______, _______, _______, KC.EQL, KC.N0, @@ -109,7 +126,7 @@ keyboard.keymap = [ _______, KC.F9, KC.F10, KC.F11, KC.F12, _______, _______, _______, _______, KC.LBRC, KC.RBRC, KC.LSHIFT(KC.INS), \ _______, KC.F5, KC.F6, KC.F7, KC.F8, _______, KC.HOME, KC.LEFT, KC.DOWN, KC.UP, KC.RGHT, KC.END, \ _______, KC.F1, KC.F2, KC.F3, KC.F4, _______, _______, _______, _______, _______, _______, KC.BSLS, \ - _______, _______, _______, _______, KC.DF(0), KC.DF(1), + _______, _______, _______, _______, KC.DF(0), KC.DF(1), ], # GUI # ,-----------------------------------------. ,-----------------------------------------. @@ -145,13 +162,13 @@ keyboard.keymap = [ # [ # SYMBOLS - KC.LEAD, KC.EXLM, KC.AT, KC.HASH, KC.DLR, KC.PERC, KC.CIRC, KC.AMPR, KC.ASTR, KC.LPRN, KC.RPRN, KC.DEL, \ + _______, KC.EXLM, KC.AT, KC.HASH, KC.DLR, KC.PERC, KC.CIRC, KC.AMPR, KC.ASTR, KC.LPRN, KC.RPRN, KC.DEL, \ _______, KC.RGB_HUI, KC.RGB_HUD, KC.RGB_VAI, KC.RGB_VAD, _______, _______, _______, _______, KC.LBRC, KC.RBRC, _______, \ - _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \ + _______, KC.RGB_RST, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \ KC.RGB_TOG, _______, _______, _______, _______, _______, ] ] if __name__ == '__main__': - keyboard.go() + keyboard.go(hid_type=HIDModes.BLE) diff --git a/user_keymaps/kdb424/gherkin.py b/user_keymaps/kdb424/gherkin.py deleted file mode 100644 index 6df6978..0000000 --- a/user_keymaps/kdb424/gherkin.py +++ /dev/null @@ -1,87 +0,0 @@ -import board - -from kmk.consts import UnicodeMode -from kmk.handlers.sequences import compile_unicode_string_sequences, send_string -from kmk.keys import KC -from kmk.kmk_keyboard import KMKKeyboard -from kmk.matrix import DiodeOrientation -from kmk.types import AttrDict - -keyboard = KMKKeyboard() - -''' -Converter/handwire: - -PB5: SCL -PB4: SDA -PE6: A0 -PD7: A1 -PC6: A2 -PD4: A3 -PD0: A4 - -PB6: D2 -PB2: TX -PB3: RX -PB1: MI -PF7: MO -PF6: SCK -PF5: A5 - -Mosfet on B5 to control backlight -''' - -keyboard.col_pins = (board.A4, board.A2, board.A3, board.A1, board.A0, board.SDA) -keyboard.row_pins = (board.D2, board.TX, board.RX, board.MISO, board.MOSI) - -# Kyle is fucking stupid -keyboard.col_pins = tuple(reversed(keyboard.col_pins)) -keyboard.row_pins = tuple(reversed(keyboard.row_pins)) - -keyboard.diode_orientation = DiodeOrientation.COLUMNS - - -# ------------------User level config variables --------------------------------------- -keyboard.unicode_mode = UnicodeMode.LINUX -keyboard.tap_time = 350 -keyboard.leader_timeout = 2000 -keyboard.debug_enabled = False - -emoticons = compile_unicode_string_sequences({ - # Emoticons, but fancier - 'ANGRY_TABLE_FLIP': r'(ノಠ痊ಠ)ノ彡┻━┻', - 'CHEER': r'+。:.゚ヽ(´∀。)ノ゚.:。+゚゚+。:.゚ヽ(*´∀)ノ゚.:。+゚', - 'TABLE_FLIP': r'(╯°□°)╯︵ ┻━┻', - 'WAT': r'⊙.☉', - 'FF': r'凸(゚Д゚#)', - 'F': r'( ̄^ ̄)凸', - 'MEH': r'╮( ̄_ ̄)╭', - 'YAY': r'o(^▽^)o', -}) - -# ---------------------- Leader Key Macros -------------------------------------------- - -keyboard.leader_dictionary = { - 'flip': emoticons.ANGRY_TABLE_FLIP, - 'cheer': emoticons.CHEER, - 'wat': emoticons.WAT, - 'ff': emoticons.FF, - 'f': emoticons.F, - 'meh': emoticons.MEH, - 'yay': emoticons.YAY, -} - -WPM = send_string('Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Bibendum arcu vitae elementum curabitur vitae nunc sed. Facilisis sed odio morbi quis.') - -# ---------------------- Keymap --------------------------------------------------------- - -keyboard.keymap = [ - [ - KC.GESC, KC.W, KC.E, KC.R, KC.T, KC.Y, KC.U, KC.I, KC.O, KC.P, - KC.A, KC.S, KC.D, KC.F, KC.G, KC.H, KC.J, KC.K, KC.L, KC.ESC, - KC.Z, KC.X, KC.C, KC.V, KC.BSPC, KC.SPC, KC.B, KC.N, KC.M, KC.ENT, - ], -] - -if __name__ == '__main__': - keyboard.go() diff --git a/user_keymaps/kdb424/klanck.py b/user_keymaps/kdb424/klanck.py deleted file mode 100644 index 555d3c9..0000000 --- a/user_keymaps/kdb424/klanck.py +++ /dev/null @@ -1,90 +0,0 @@ -import board - -from kmk.consts import UnicodeMode -from kmk.handlers.sequences import compile_unicode_string_sequences, send_string -from kmk.keys import KC -from kmk.kmk_keyboard import KMKKeyboard -from kmk.matrix import DiodeOrientation -from kmk.types import AttrDict - -keyboard = KMKKeyboard() - -keyboard.col_pins = (board.A0, board.A1, board.A2, board.A3, board.A4, board.A5, board.SCK, board.MOSI, board.MISO, board.RX, board.TX, board.D4) -keyboard.row_pins = (board.D10, board.D11, board.D12, board.D13) -keyboard.diode_orientation = DiodeOrientation.COLUMNS - - -# ------------------User level config variables --------------------------------------- -keyboard.unicode_mode = UnicodeMode.LINUX -keyboard.tap_time = 350 -keyboard.leader_timeout = 2000 -keyboard.debug_enabled = False - -emoticons = compile_unicode_string_sequences({ - # Emoticons, but fancier - 'ANGRY_TABLE_FLIP': r'(ノಠ痊ಠ)ノ彡┻━┻', - 'CHEER': r'+。:.゚ヽ(´∀。)ノ゚.:。+゚゚+。:.゚ヽ(*´∀)ノ゚.:。+゚', - 'TABLE_FLIP': r'(╯°□°)╯︵ ┻━┻', - 'WAT': r'⊙.☉', - 'FF': r'凸(゚Д゚#)', - 'F': r'( ̄^ ̄)凸', - 'MEH': r'╮( ̄_ ̄)╭', - 'YAY': r'o(^▽^)o', -}) - -# ---------------------- Leader Key Macros -------------------------------------------- - -keyboard.leader_dictionary = { - 'flip': emoticons.ANGRY_TABLE_FLIP, - 'cheer': emoticons.CHEER, - 'wat': emoticons.WAT, - 'ff': emoticons.FF, - 'f': emoticons.F, - 'meh': emoticons.MEH, - 'yay': emoticons.YAY, -} - -WPM = send_string('Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Bibendum arcu vitae elementum curabitur vitae nunc sed. Facilisis sed odio morbi quis.') - -# ---------------------- Keymap --------------------------------------------------------- - -keyboard.keymap = [ - [ - # default - KC.GESC, KC.QUOTE, KC.COMMA, KC.DOT, KC.P, KC.Y, KC.F, KC.G, KC.C, KC.R, KC.L, KC.BKSP, - KC.TAB, KC.A, KC.O, KC.E, KC.U, KC.I, KC.D, KC.H, KC.T, KC.N, KC.S, KC.ENT, - KC.LSFT, KC.SCLN, KC.Q, KC.J, KC.K, KC.X, KC.B, KC.M, KC.W, KC.V, KC.Z, KC.SLSH, - KC.LCTRL, KC.LGUI, KC.LALT, KC.LEAD, KC.MO(2), KC.LT(3, KC.SPC), KC.LT(3, KC.SPC), KC.MO(4), KC.LEFT, KC.DOWN, KC.UP, KC.RIGHT, - ], - [ - # Gaming - KC.TAB, KC.QUOT, KC.COMM, KC.DOT, KC.P, KC.Y, KC.F, KC.G, KC.C, KC.R, KC.L, KC.BKSP, - KC.ESC, KC.A, KC.O, KC.E, KC.U, KC.I, KC.D, KC.H, KC.T, KC.N, KC.S, KC.ENT, - KC.LSFT, KC.SCLN, KC.Q, KC.J, KC.K, KC.X, KC.B, KC.M, KC.W, KC.V, KC.Z, KC.SLSH, - KC.LCTRL, KC.LGUI, KC.LALT, KC.F1, KC.F2, KC.SPC, KC.SPC, KC.MO(4), KC.LEFT, KC.DOWN, KC.UP, KC.RIGHT, - ], - [ - # Raise1 - KC.TILD, KC.EXLM, KC.AT, KC.HASH, KC.DLR, KC.PERC, KC.CIRC, KC.AMPR, KC.ASTR, KC.LPRN, KC.RPRN, KC.DEL, - KC.TRNS, KC.NO, KC.NO, KC.NO, KC.NO, KC.NO, KC.NO, KC.NO, KC.NO, KC.LBRC, KC.RBRC, KC.BSLS, - KC.TRNS, KC.NO, KC.NO, KC.NO, KC.NO, KC.NO, KC.NO, KC.NO, KC.INS, KC.PGDN, KC.PGUP, KC.MINS, - KC.RESET, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.NO, KC.NO, KC.EQL, KC.HOME, KC.VOLD, KC.VOLU, KC.END, - ], - [ - # Raise2 - KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.N7, KC.N8, KC.N9, KC.BKSP, - KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.N4, KC.N5, KC.N6, KC.NO, - KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.N1, KC.N2, KC.N3, KC.NO, - KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.N0, KC.N0, KC.PDOT, KC.ENT, - ], - [ - # Raise3 - WPM, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.F10, KC.F11, KC.F12, KC.LSHIFT(KC.INS), - KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.F7, KC.F8, KC.F9, KC.NO, - KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.F4, KC.F5, KC.F6, KC.NO, - KC.DF(0), KC.DF(1), KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.F1, KC.F2, KC.F3, KC.NO, - ], -] - -if __name__ == '__main__': - keyboard.go() diff --git a/user_keymaps/kdb424/levinson_r2.py b/user_keymaps/kdb424/levinson_r2.py deleted file mode 100644 index 5ae7352..0000000 --- a/user_keymaps/kdb424/levinson_r2.py +++ /dev/null @@ -1,93 +0,0 @@ -from kmk.boards.converter.keebio.levinson_r2 import KMKKeyboard -from kmk.consts import LeaderMode, UnicodeMode -from kmk.handlers.sequences import compile_unicode_string_sequences -from kmk.keys import KC - -keyboard = KMKKeyboard() - -# ------------------User level config variables --------------------------------------- -keyboard.leader_mode = LeaderMode.TIMEOUT -keyboard.unicode_mode = UnicodeMode.LINUX -keyboard.tap_time = 150 -keyboard.leader_timeout = 2000 -keyboard.debug_enabled = True - -keyboard.rgb_config['num_pixels'] = 16 -keyboard.rgb_config['val_limit'] = 150 -keyboard.rgb_config['hue_step'] = 10 -keyboard.rgb_config['sat_step'] = 5 -keyboard.rgb_config['val_step'] = 5 -keyboard.rgb_config['hue_default'] = 260 -keyboard.rgb_config['sat_default'] = 100 -keyboard.rgb_config['val_default'] = 20 -keyboard.rgb_config['knight_effect_length'] = 6 -keyboard.rgb_config['animation_mode'] = 'swirl' -keyboard.rgb_config['animation_speed'] = 2 -keyboard.debug_enabled = False - -emoticons = compile_unicode_string_sequences({ - # Emoticons, but fancier - 'ANGRY_TABLE_FLIP': r'(ノಠ痊ಠ)ノ彡┻━┻', - 'CHEER': r'+。:.゚ヽ(´∀。)ノ゚.:。+゚゚+。:.゚ヽ(*´∀)ノ゚.:。+゚', - 'TABLE_FLIP': r'(╯°□°)╯︵ ┻━┻', - 'WAT': r'⊙.☉', - 'FF': r'凸(゚Д゚#)', - 'F': r'( ̄^ ̄)凸', - 'MEH': r'╮( ̄_ ̄)╭', - 'YAY': r'o(^▽^)o', -}) - -# ---------------------- Leader Key Macros -------------------------------------------- - -keyboard.leader_dictionary = { - 'flip': emoticons.ANGRY_TABLE_FLIP, - 'cheer': emoticons.CHEER, - 'wat': emoticons.WAT, - 'ff': emoticons.FF, - 'f': emoticons.F, - 'meh': emoticons.MEH, - 'yay': emoticons.YAY, -} - -# ---------------------- Keymap --------------------------------------------------------- - -keyboard.keymap = [ - [ - # default - KC.GESC, KC.QUOTE, KC.COMMA, KC.DOT, KC.P, KC.Y, KC.F, KC.G, KC.C, KC.R, KC.L, KC.BKSP, - KC.TAB, KC.A, KC.O, KC.E, KC.U, KC.I, KC.D, KC.H, KC.T, KC.N, KC.S, KC.ENT, - KC.LSFT, KC.SCLN, KC.Q, KC.J, KC.K, KC.X, KC.B, KC.M, KC.W, KC.V, KC.Z, KC.SLSH, - KC.LCTRL, KC.LGUI, KC.LALT, KC.RGB_TOG, KC.MO(2), KC.LT(3, KC.SPC), KC.LT(3, KC.SPC), KC.MO(4), KC.LEFT, KC.DOWN, KC.UP, KC.RIGHT, - ], - [ - # Gaming - KC.TAB, KC.QUOT, KC.COMM, KC.DOT, KC.P, KC.Y, KC.F, KC.G, KC.C, KC.R, KC.L, KC.BKSP, - KC.ESC, KC.A, KC.O, KC.E, KC.U, KC.I, KC.D, KC.H, KC.T, KC.N, KC.S, KC.ENT, - KC.LSFT, KC.SCLN, KC.Q, KC.J, KC.K, KC.X, KC.B, KC.M, KC.W, KC.V, KC.Z, KC.SLSH, - KC.LCTRL, KC.LGUI, KC.LALT, KC.F1, KC.F2, KC.SPC, KC.SPC, KC.MO(4), KC.LEFT, KC.DOWN, KC.UP, KC.RIGHT, - ], - [ - # Raise1 - KC.TILD, KC.EXLM, KC.AT, KC.HASH, KC.DLR, KC.PERC, KC.CIRC, KC.AMPR, KC.ASTR, KC.LPRN, KC.RPRN, KC.DEL, - KC.TRNS, KC.NO, KC.NO, KC.NO, KC.NO, KC.NO, KC.NO, KC.NO, KC.NO, KC.LBRC, KC.RBRC, KC.BSLS, - KC.TRNS, KC.NO, KC.NO, KC.NO, KC.NO, KC.NO, KC.NO, KC.NO, KC.INS, KC.PGDN, KC.PGUP, KC.MINS, - KC.RESET, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.NO, KC.NO, KC.EQL, KC.HOME, KC.VOLD, KC.VOLU, KC.END, - ], - [ - # Raise2 - KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.N7, KC.N8, KC.N9, KC.BKSP, - KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.N4, KC.N5, KC.N6, KC.NO, - KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.N1, KC.N2, KC.N3, KC.NO, - KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.N0, KC.N0, KC.PDOT, KC.ENT, - ], - [ - # Raise3 - KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.F10, KC.F11, KC.F12, KC.LSHIFT(KC.INS), - KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.F7, KC.F8, KC.F9, KC.NO, - KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.F4, KC.F5, KC.F6, KC.NO, - KC.DF(0), KC.DF(1), KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.TRNS, KC.F1, KC.F2, KC.F3, KC.NO, - ], -] - -if __name__ == '__main__': - keyboard.go() diff --git a/user_keymaps/kdb424/luddite.py b/user_keymaps/kdb424/luddite.py index 1e2ac2f..948e145 100644 --- a/user_keymaps/kdb424/luddite.py +++ b/user_keymaps/kdb424/luddite.py @@ -1,5 +1,8 @@ -from kmk.boards.converter.fourtypercentclub.luddite import KMKKeyboard +from kb import KMKKeyboard +from kmk.extensions.rgb import RGB from kmk.keys import KC +from kmk.modules.layers import Layers +from kmk.modules.modtap import ModTap keyboard = KMKKeyboard() @@ -7,17 +10,6 @@ keyboard = KMKKeyboard() keyboard.tap_time = 150 -keyboard.rgb_config['num_pixels'] = 16 -keyboard.rgb_config['val_limit'] = 150 -keyboard.rgb_config['hue_step'] = 10 -keyboard.rgb_config['sat_step'] = 5 -keyboard.rgb_config['val_step'] = 5 -keyboard.rgb_config['hue_default'] = 260 -keyboard.rgb_config['sat_default'] = 100 -keyboard.rgb_config['val_default'] = 0 -keyboard.rgb_config['knight_effect_length'] = 6 -keyboard.rgb_config['animation_mode'] = 'static' -keyboard.rgb_config['animation_speed'] = 2 keyboard.debug_enabled = False @@ -27,13 +19,20 @@ BASE = 0 GAMING = 1 FN1 = 2 +rgb_ext = RGB(pixel_pin=keyboard.rgb_pixel_pin, num_pixels=16) +layers_ext = Layers() +modtap = ModTap() + +keyboard.modules = [layers_ext, modtap] +keyboard.extensions = [rgb_ext] + _______ = KC.TRNS XXXXXXX = KC.NO 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(2, KC.SPC) +SPC = KC.LT(FN1, KC.SPC) # ---------------------- Keymap --------------------------------------------------------- @@ -43,7 +42,7 @@ keyboard.keymap = [ # df [ KC.GESC, KC.N1, KC.N2, KC.N3, KC.N4, KC.N5, KC.N6, KC.N7, KC.N8, KC.N9, KC.N0, KC.LBRC, KC.RBRC, KC.BSPC, - KC.LEAD, KC.QUOT, KC.COMM, KC.DOT, KC.P, KC.Y, KC.F, KC.G, KC.C, KC.R, KC.L, KC.SLSH, KC.EQL, KC.BSLS, + KC.RGB_TOG, KC.QUOT, KC.COMM, KC.DOT, KC.P, KC.Y, KC.F, KC.G, KC.C, KC.R, KC.L, KC.SLSH, KC.EQL, KC.BSLS, KC.TAB, KC.A, KC.O, KC.E, KC.U, KC.I, KC.D, KC.H, KC.T, KC.N, KC.S, KC.MINS, KC.ENT, KC.LSFT, KC.SCLN, KC.Q, KC.J, KC.K, KC.X, KC.B, KC.M, KC.W, KC.V, KC.Z, KC.RSFT, KC.LCTL, KC.LGUI, KC.LALT, SPC, KC.LEFT, KC.DOWN, KC.UP, KC.RIGHT, @@ -52,7 +51,7 @@ keyboard.keymap = [ # df [ KC.GESC, KC.N1, KC.N2, KC.N3, KC.N4, KC.N5, KC.N6, KC.N7, KC.N8, KC.N9, KC.N0, KC.LBRC, KC.RBRC, KC.BSPC, - KC.LEAD, KC.QUOT, KC.COMM, KC.DOT, KC.P, KC.Y, KC.F, KC.G, KC.C, KC.R, KC.L, KC.SLSH, KC.EQL, KC.BSLS, + KC.RGB_TOG, KC.QUOT, KC.COMM, KC.DOT, KC.P, KC.Y, KC.F, KC.G, KC.C, KC.R, KC.L, KC.SLSH, KC.EQL, KC.BSLS, KC.TAB, KC.A, KC.O, KC.E, KC.U, KC.I, KC.D, KC.H, KC.T, KC.N, KC.S, KC.MINS, KC.ENT, KC.LSFT, KC.SCLN, KC.Q, KC.J, KC.K, KC.X, KC.B, KC.M, KC.W, KC.V, KC.Z, KC.RSFT, KC.LCTL, KC.LGUI, KC.LALT, KC.SPC, LEFT_LAY, KC.DOWN, KC.UP, KC.RIGHT, @@ -62,8 +61,8 @@ keyboard.keymap = [ [ KC.GESC, KC.F1, KC.F2, KC.F3, KC.F4, KC.F5, KC.F6, KC.F7, KC.F8, KC.F9, KC.F10, KC.F11, KC.F12, KC.DEL, KC.RESET, KC.RGB_HUD, KC.RGB_HUI, _______, _______, _______, _______, _______, _______, KC.RGB_M_S, _______, _______, KC.VOLU, SHFT_INS, - _______, KC.RGB_SAD, KC.RGB_SAI, _______, _______, _______, _______, _______, KC.RGB_TOG, _______, KC.RGB_M_P, KC.VOLD, _______, - _______, KC.RGB_VAD, KC.RGB_VAI, _______, _______, _______, _______, _______, _______, _______, _______, _______, + KC.RGB_ANI, KC.RGB_SAD, KC.RGB_SAI, _______, _______, _______, _______, _______, KC.RGB_TOG, _______, KC.RGB_M_P, KC.VOLD, _______, + KC.RGB_AND, KC.RGB_VAD, KC.RGB_VAI, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC.DF(0), KC.DF(1), ], ] diff --git a/user_keymaps/kdb424/nyquist_r2.py b/user_keymaps/kdb424/nyquist_r2.py index ad5fbd6..d6076a5 100644 --- a/user_keymaps/kdb424/nyquist_r2.py +++ b/user_keymaps/kdb424/nyquist_r2.py @@ -1,102 +1,49 @@ -from kmk.boards.converter.keebio.nyquist_r2 import KMKKeyboard +import board + +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.layers import Layers +from kmk.modules.modtap import ModTap +from kmk.modules.split import Split keyboard = KMKKeyboard() # ------------------User level config variables --------------------------------------- keyboard.tap_time = 150 -keyboard.leader_timeout = 2000 -keyboard.debug_enabled = False -# RGB Config (underglow) -keyboard.rgb_config['num_pixels'] = 12 -keyboard.rgb_config['val_limit'] = 150 -keyboard.rgb_config['hue_step'] = 10 -keyboard.rgb_config['sat_step'] = 5 -keyboard.rgb_config['val_step'] = 5 -keyboard.rgb_config['hue_default'] = 260 -keyboard.rgb_config['sat_default'] = 100 -keyboard.rgb_config['val_default'] = 40 -keyboard.rgb_config['knight_effect_length'] = 4 -keyboard.rgb_config['animation_mode'] = 'static' -keyboard.rgb_config['animation_speed'] = 1 -keyboard.debug_enabled = False +layers = Layers() +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 = [modtap, layers, split] +keyboard.extensions = [rgb_ext] _______ = KC.TRNS XXXXXXX = KC.NO SHFT_INS = KC.LSHIFT(KC.INS) -TAB_UP = KC.RCTRL(KC.PGUP) -TAB_DOWN = KC.RCTRL(KC.PGDN) BASE = KC.DF(0) -LT2_SP = KC.LT(3, KC.SPC) GAMING = KC.DF(1) - -HACHEEJ = simple_key_sequence(( - KC.LSFT(KC.SCOLON), KC.H, KC.A, KC.C, KC.H, KC.E, KC.E, KC.J, KC.A, KC.I, KC.L, KC.N1, KC.LSFT(KC.SCOLON), - KC.LSFT(KC.SCOLON), KC.H, KC.A, KC.C, KC.H, KC.E, KC.E, KC.J, KC.A, KC.I, KC.L, KC.N2, KC.LSFT(KC.SCOLON), - KC.LSFT(KC.SCOLON), KC.H, KC.A, KC.C, KC.H, KC.E, KC.E, KC.J, KC.A, KC.I, KC.L, KC.N3, KC.LSFT(KC.SCOLON), - KC.LSFT(KC.ENT), - KC.LSFT(KC.SCOLON), KC.H, KC.A, KC.C, KC.H, KC.E, KC.E, KC.J, KC.A, KC.I, KC.L, KC.N4, KC.LSFT(KC.SCOLON), - KC.LSFT(KC.SCOLON), KC.H, KC.A, KC.C, KC.H, KC.E, KC.E, KC.J, KC.A, KC.I, KC.L, KC.N5, KC.LSFT(KC.SCOLON), - KC.LSFT(KC.SCOLON), KC.H, KC.A, KC.C, KC.H, KC.E, KC.E, KC.J, KC.A, KC.I, KC.L, KC.N6, KC.LSFT(KC.SCOLON), - KC.LSFT(KC.ENT), - KC.LSFT(KC.SCOLON), KC.H, KC.A, KC.C, KC.H, KC.E, KC.E, KC.J, KC.A, KC.I, KC.L, KC.N7, KC.LSFT(KC.SCOLON), - KC.LSFT(KC.SCOLON), KC.H, KC.A, KC.C, KC.H, KC.E, KC.E, KC.J, KC.A, KC.I, KC.L, KC.N8, KC.LSFT(KC.SCOLON), - KC.LSFT(KC.SCOLON), KC.H, KC.A, KC.C, KC.H, KC.E, KC.E, KC.J, KC.A, KC.I, KC.L, KC.N9, KC.LSFT(KC.SCOLON), - KC.ENT - )) - -HACHEEF = simple_key_sequence(( - KC.LSFT(KC.SCOLON), KC.H, KC.A, KC.C, KC.H, KC.E, KC.E, KC.N1, KC.LSFT(KC.SCOLON), - KC.LSFT(KC.SCOLON), KC.H, KC.A, KC.C, KC.H, KC.E, KC.E, KC.N2, KC.LSFT(KC.SCOLON), - KC.LSFT(KC.SCOLON), KC.H, KC.A, KC.C, KC.H, KC.E, KC.E, KC.N3, KC.LSFT(KC.SCOLON), - KC.LSFT(KC.ENT), - KC.LSFT(KC.SCOLON), KC.H, KC.A, KC.C, KC.H, KC.E, KC.E, KC.N4, KC.LSFT(KC.SCOLON), - KC.LSFT(KC.SCOLON), KC.H, KC.A, KC.C, KC.H, KC.E, KC.E, KC.N5, KC.LSFT(KC.SCOLON), - KC.LSFT(KC.SCOLON), KC.H, KC.A, KC.C, KC.H, KC.E, KC.E, KC.N6, KC.LSFT(KC.SCOLON), - KC.LSFT(KC.ENT), - KC.LSFT(KC.SCOLON), KC.H, KC.A, KC.C, KC.H, KC.E, KC.E, KC.N7, KC.LSFT(KC.SCOLON), - KC.LSFT(KC.SCOLON), KC.H, KC.A, KC.C, KC.H, KC.E, KC.E, KC.N8, KC.LSFT(KC.SCOLON), - KC.LSFT(KC.SCOLON), KC.H, KC.A, KC.C, KC.H, KC.E, KC.E, KC.N9, KC.LSFT(KC.SCOLON), - KC.ENT - )) - -THIGHS = simple_key_sequence(( - KC.LSFT(KC.SCOLON), KC.T, KC.H, KC.I, KC.G, KC.H, KC.S, KC.N1, KC.LSFT(KC.SCOLON), - KC.LSFT(KC.SCOLON), KC.T, KC.H, KC.I, KC.G, KC.H, KC.S, KC.N2, KC.LSFT(KC.SCOLON), - KC.LSFT(KC.SCOLON), KC.T, KC.H, KC.I, KC.G, KC.H, KC.S, KC.N3, KC.LSFT(KC.SCOLON), - KC.LSFT(KC.SCOLON), KC.T, KC.H, KC.I, KC.G, KC.H, KC.S, KC.N4, KC.LSFT(KC.SCOLON), - KC.LSFT(KC.ENT), - KC.LSFT(KC.SCOLON), KC.T, KC.H, KC.I, KC.G, KC.H, KC.S, KC.N5, KC.LSFT(KC.SCOLON), - KC.LSFT(KC.SCOLON), KC.T, KC.H, KC.I, KC.G, KC.H, KC.S, KC.N6, KC.LSFT(KC.SCOLON), - KC.LSFT(KC.SCOLON), KC.T, KC.H, KC.I, KC.G, KC.H, KC.S, KC.N7, KC.LSFT(KC.SCOLON), - KC.LSFT(KC.SCOLON), KC.T, KC.H, KC.I, KC.G, KC.H, KC.S, KC.N8, KC.LSFT(KC.SCOLON), - KC.LSFT(KC.ENT), - KC.LSFT(KC.SCOLON), KC.T, KC.H, KC.I, KC.G, KC.H, KC.S, KC.N9, KC.LSFT(KC.SCOLON), - KC.LSFT(KC.SCOLON), KC.T, KC.H, KC.I, KC.G, KC.H, KC.S, KC.N1, KC.N0, KC.LSFT(KC.SCOLON), - KC.LSFT(KC.SCOLON), KC.T, KC.H, KC.I, KC.G, KC.H, KC.S, KC.N1, KC.N1, KC.LSFT(KC.SCOLON), - KC.LSFT(KC.SCOLON), KC.T, KC.H, KC.I, KC.G, KC.H, KC.S, KC.N1, KC.N2, KC.LSFT(KC.SCOLON), - KC.LSFT(KC.ENT), - KC.LSFT(KC.SCOLON), KC.T, KC.H, KC.I, KC.G, KC.H, KC.S, KC.N1, KC.N3, KC.LSFT(KC.SCOLON), - KC.LSFT(KC.SCOLON), KC.T, KC.H, KC.I, KC.G, KC.H, KC.S, KC.N1, KC.N4, KC.LSFT(KC.SCOLON), - KC.LSFT(KC.SCOLON), KC.T, KC.H, KC.I, KC.G, KC.H, KC.S, KC.N1, KC.N5, KC.LSFT(KC.SCOLON), - KC.LSFT(KC.SCOLON), KC.T, KC.H, KC.I, KC.G, KC.H, KC.S, KC.N1, KC.N6, KC.LSFT(KC.SCOLON), - KC.ENT - )) +LT1_SP = KC.MO(2) +LT2_SP = KC.LT(3, KC.SPC) +TAB_SB = KC.LT(5, KC.TAB) +SUPER_L = KC.LM(4, KC.LGUI) # ---------------------- Keymap --------------------------------------------------------- keyboard.keymap = [ [ # df - KC.GESC, KC.N1, KC.N2, KC.N3, KC.N4, KC.N5, KC.N6, KC.N7, KC.N8, KC.N9, KC.N0, KC.DEL, - KC.GRV, KC.QUOTE, KC.COMMA, KC.DOT, KC.P, KC.Y, KC.F, KC.G, KC.C, KC.R, KC.L, KC.BKSP, - KC.TAB, KC.A, KC.O, KC.E, KC.U, KC.I, KC.D, KC.H, KC.T, KC.N, KC.S, KC.ENT, - KC.LSFT, KC.SCLN, KC.Q, KC.J, KC.K, KC.X, KC.B, KC.M, KC.W, KC.V, KC.Z, KC.SLSH, - KC.LCTRL, KC.LGUI, KC.LALT, KC.RGB_TOG, KC.MO(2), LT2_SP, KC.SPC, KC.MO(4), KC.LEFT, KC.DOWN, KC.UP, KC.RIGHT, + KC.GRV, KC.N1, KC.N2, KC.N3, KC.N4, KC.N5, KC.N6, KC.N7, KC.N8, KC.N9, KC.N0, KC.DEL, + KC.GESC, KC.QUOT, KC.COMM, KC.DOT, KC.P, KC.Y, KC.F, KC.G, KC.C, KC.R, KC.L, KC.BSPC, + TAB_SB, KC.A, KC.O, KC.E, KC.U, KC.I, KC.D, KC.H, KC.T, KC.N, KC.S, KC.ENT, + KC.LSFT, KC.SCLN, KC.Q, KC.J, KC.K, KC.X, KC.B, KC.M, KC.W, KC.V, KC.Z, KC.SLSH, + KC.LCTRL, KC.LGUI, KC.LALT, KC.LALT, SUPER_L, LT1_SP, LT2_SP, KC.LCTL, KC.LEFT, KC.DOWN, KC.UP, KC.RIGHT, ], + [ # gw KC.GESC, KC.N1, KC.N2, KC.N3, KC.N4, KC.N5, KC.N6, KC.N7, KC.N8, KC.N9, KC.N0, KC.DEL, @@ -108,26 +55,34 @@ keyboard.keymap = [ [ # r1 KC.GESC, KC.N1, KC.N2, KC.N3, KC.N4, KC.N5, KC.N6, KC.N7, KC.N8, KC.N9, KC.N0, KC.DEL, - KC.TILD, KC.EXLM, KC.AT, KC.HASH, KC.DLR, KC.PERC, KC.CIRC, KC.AMPR, KC.ASTR, KC.LPRN, KC.RPRN, KC.DEL, - _______, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC.LBRC, KC.RBRC, KC.BSLS, - _______, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC.INS, _______, _______, KC.MINS, - KC.RESET, _______, _______, _______, _______, _______, _______, KC.EQL, KC.HOME, KC.PGDN, KC.PGUP, KC.END, + _______, _______, _______, _______, _______, _______, _______, XXXXXXX, KC.N7, KC.N8, KC.N9, KC.DEL, + _______, _______, _______, _______, _______, _______, XXXXXXX, XXXXXXX, KC.N4, KC.N5, KC.N6, KC.BSLS, + _______, _______, _______, _______, _______, _______, XXXXXXX, XXXXXXX, KC.N1, KC.N2, KC.N3, KC.MINS, + KC.RESET, _______, _______, _______, _______, _______, _______, KC.EQL, KC.N0, XXXXXXX, XXXXXXX, XXXXXXX, ], [ # r2 - KC.GESC, KC.N1, KC.N2, KC.N3, KC.N4, KC.N5, KC.N6, KC.N7, KC.N8, KC.N9, KC.N0, KC.DEL, - _______, _______, _______, _______, _______, _______, HACHEEF, THIGHS, KC.N7, KC.N8, KC.N9, KC.BKSP, - _______, _______, _______, _______, _______, _______, _______, HACHEEJ, KC.N4, KC.N5, KC.N6, XXXXXXX, - _______, _______, _______, _______, _______, _______, _______, _______, KC.N1, KC.N2, KC.N3, XXXXXXX, - _______, _______, _______, _______, _______, _______, _______, _______, KC.N0, KC.N0, KC.PDOT, KC.ENT, + KC.GESC, KC.N1, KC.N2, KC.N3, KC.N4, KC.N5, KC.N6, KC.N7, KC.N8, KC.N9, KC.N0, KC.DEL, + _______, KC.F9, KC.F10, KC.F11, KC.F12, _______, _______, _______, _______, KC.LBRC, KC.RBRC, KC.LSHIFT(KC.INS), + _______, KC.F5, KC.F6, KC.F7, KC.F8, _______, KC.HOME, KC.LEFT, KC.DOWN, KC.UP, KC.RGHT, KC.END, + _______, KC.F1, KC.F2, KC.F3, KC.F4, _______, _______, _______, _______, _______, _______, KC.BSLS, + _______, _______, _______, _______, _______, _______, _______, _______, KC.DF(0), KC.DF(1), _______, _______ ], [ - # r3 - KC.GESC, KC.RGB_M_P, KC.RGB_M_K, KC.RGB_M_B, KC.RGB_M_BR, KC.RGB_M_S, _______, _______, KC.F10, KC.F11, KC.F12, KC.DEL, - KC.RGB_ANI, KC.RGB_HUD, KC.RGB_HUI, _______, _______, _______, _______, _______, KC.F7, KC.F8, KC.F9, SHFT_INS, - KC.RGB_AND, KC.RGB_SAD, KC.RGB_SAI, _______, _______, _______, _______, _______, KC.F4, KC.F5, KC.F6, TAB_UP, - _______, KC.RGB_VAD, KC.RGB_VAI, _______, _______, _______, _______, _______, KC.F1, KC.F2, KC.F4, TAB_DOWN, - BASE, GAMING, _______, _______, _______, _______, _______, _______, _______, _______, _______, XXXXXXX, + # GUI + KC.GESC, KC.RGB_M_P, KC.RGB_M_K, KC.RGB_M_B, KC.RGB_M_BR, KC.RGB_M_S, _______, _______, KC.F10, KC.F11, KC.F12, KC.DEL, + _______, KC.N1, KC.N2, KC.N3, KC.N4, KC.N5, _______, _______, _______, _______, _______, _______, + _______, KC.N6, KC.N7, KC.N8, KC.N9, KC.N0, _______, _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ + ], + [ + # Symbols + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, + _______, KC.EXLM, KC.AT, KC.HASH, KC.DLR, KC.PERC, KC.CIRC, KC.AMPR, KC.ASTR, KC.LPRN, KC.RPRN, KC.DEL, + _______, KC.RGB_HUI, KC.RGB_HUD, KC.RGB_VAI, KC.RGB_VAD, _______, _______, _______, _______, KC.LBRC, KC.RBRC, _______, + _______, KC.RGB_RST, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, + _______, _______, _______, KC.RGB_TOG, _______, _______, _______, _______, _______, _______, _______, _______ ], ] diff --git a/user_keymaps/klardotsh/iris_r2.py b/user_keymaps/klardotsh/iris_r2.py index dab29a1..494f2f6 100644 --- a/user_keymaps/klardotsh/iris_r2.py +++ b/user_keymaps/klardotsh/iris_r2.py @@ -1,10 +1,15 @@ -from kmk.boards.converter.keebio.iris_r2 import KMKKeyboard -from kmk.consts import LeaderMode, UnicodeMode +from kb import KMKKeyboard +from kmk.consts import UnicodeMode from kmk.handlers.sequences import compile_unicode_string_sequences as cuss from kmk.handlers.sequences import send_string from kmk.keys import KC +from kmk.modules.layers import Layers +from kmk.modules.split import Split, SplitType keyboard = KMKKeyboard() +layers_ext = Layers() +split = Split(split_type=SplitType.UART) +keyboard.modules = [layers_ext, split] keyboard.debug_enabled = False keyboard.unicode_mode = UnicodeMode.LINUX @@ -43,24 +48,6 @@ emoticons = cuss({ WPM = send_string('Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Bibendum arcu vitae elementum curabitur vitae nunc sed. Facilisis sed odio morbi quis.') -keyboard.leader_mode = LeaderMode.ENTER -keyboard.leader_dictionary = { - 'hello': send_string('hello world from kmk macros'), - 'wpm': WPM, - 'atf': emoticons.ANGRY_TABLE_FLIP, - 'tf': emoticons.TABLE_FLIP, - 'fca': emoticons.FLAG_CA, - 'fus': emoticons.FLAG_US, - 'cel': emoticons.CELEBRATORY_GLITTER, - 'shr': emoticons.SHRUGGIE, - 'shre': emoticons.SHRUG_EMOJI, - 'poop': emoticons.POOP, - 'joy': emoticons.FACE_JOY, - 'ls': KC.LGUI(KC.HOME), # Lock screen - 'cw': KC.LGUI(KC.END), # Close window - 'dbg': KC.DBG, -} - _______ = KC.TRNS xxxxxxx = KC.NO HELLA_TD = KC.TD( @@ -70,6 +57,7 @@ HELLA_TD = KC.TD( KC.TG(1), ) + keyboard.keymap = [ [ KC.GESC, KC.N1, KC.N2, KC.N3, KC.N4, KC.N5, KC.N6, KC.N7, KC.N8, KC.N9, KC.N0, KC.BSPC, @@ -82,7 +70,7 @@ keyboard.keymap = [ _______, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, KC.F10, KC.F11, KC.F12, xxxxxxx, xxxxxxx, _______, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, KC.F7, KC.F8, KC.F9, xxxxxxx, xxxxxxx, KC.EQUAL, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, KC.INS, KC.F4, KC.F5, KC.F6, xxxxxxx, xxxxxxx, xxxxxxx, - xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, KC.LEAD, _______, KC.F1, KC.F2, KC.F3, xxxxxxx, xxxxxxx, _______, + xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, xxxxxxx, KC.NO, _______, KC.F1, KC.F2, KC.F3, xxxxxxx, xxxxxxx, _______, KC.HOME, KC.END, _______, xxxxxxx, KC.PGUP, KC.PGDN, ], [ diff --git a/user_keymaps/klardotsh/klarank_featherm4.py b/user_keymaps/klardotsh/klarank_featherm4.py index 233780b..0a7be96 100644 --- a/user_keymaps/klardotsh/klarank_featherm4.py +++ b/user_keymaps/klardotsh/klarank_featherm4.py @@ -1,13 +1,15 @@ -from kmk.boards.klarank import KMKKeyboard +from kb import KMKKeyboard from kmk.consts import UnicodeMode -from kmk.extensions.leader import Leader, LeaderMode from kmk.handlers.sequences import compile_unicode_string_sequences as cuss from kmk.handlers.sequences import send_string from kmk.keys import KC, make_key +from kmk.modules.layers import Layers keyboard = KMKKeyboard() +layers_ext = Layers() +keyboard.modules = [layers_ext] -keyboard.debug_enabled = True +keyboard.debug_enabled = False keyboard.unicode_mode = UnicodeMode.LINUX keyboard.tap_time = 750 @@ -52,22 +54,6 @@ HELLA_TD = KC.TD( KC.TG(1), ) -leader_ext = Leader(mode=LeaderMode.ENTER, sequences={ - 'hello': send_string('hello world from kmk macros'), - 'wpm': WPM, - 'atf': emoticons.ANGRY_TABLE_FLIP, - 'tf': emoticons.TABLE_FLIP, - 'fca': emoticons.FLAG_CA, - 'fus': emoticons.FLAG_US, - 'cel': emoticons.CELEBRATORY_GLITTER, - 'shr': emoticons.SHRUGGIE, - 'poop': emoticons.POOP, - 'ls': KC.LGUI(KC.HOME), - 'dbg': KC.DBG, -}) - -keyboard.extensions = [leader_ext] - def shrek_is_life(*args, **kwargs): ''' @@ -107,7 +93,7 @@ keyboard.keymap = [ KC.GESC, KC.QUOT, KC.COMM, KC.DOT, KC.P, KC.Y, KC.F, KC.G, KC.C, KC.R, KC.L, KC.BSPC, KC.TAB, KC.A, KC.O, KC.E, KC.U, KC.I, KC.D, KC.H, KC.T, KC.N, KC.S, KC.ENT, KC.LGUI, KC.SCLN, KC.Q, KC.J, KC.K, KC.X, KC.B, KC.M, KC.W, KC.V, KC.Z, KC.LALT, - KC.LCTL, KC.LEAD, KC.LSHIFT(KC.LGUI), KC.MO(2), KC.MO(3), KC.LSFT, KC.SPC, KC.MO(1), KC.LEFT, KC.DOWN, KC.UP, KC.RGHT, + KC.LCTL, KC.NO, KC.LSHIFT(KC.LGUI), KC.MO(2), KC.MO(3), KC.LSFT, KC.SPC, KC.MO(1), KC.LEFT, KC.DOWN, KC.UP, KC.RGHT, ], [ diff --git a/user_keymaps/rk463345/levinson_r2.py b/user_keymaps/rk463345/levinson_r2.py index aa8dadc..c807f9f 100755 --- a/user_keymaps/rk463345/levinson_r2.py +++ b/user_keymaps/rk463345/levinson_r2.py @@ -1,28 +1,25 @@ -from kmk.boards.converter.keebio.levinson_r2 import KMKKeyboard -from kmk.consts import LeaderMode, UnicodeMode +from kb import KMKKeyboard +from kmk.consts import UnicodeMode +from kmk.extensions.rgb import RGB from kmk.handlers.sequences import compile_unicode_string_sequences from kmk.keys import KC +from kmk.modules.layers import Layers +from kmk.modules.media_keys import MediaKeys +from kmk.modules.split import Split, SplitType keyboard = KMKKeyboard() +layers = Layers() +media_keys = MediaKeys() +split = Split(split_type=SplitType.UART) +rgb_ext = RGB(pixel_pin=keyboard.rgb_pixel_pin, num_pixels=16, val_limit=150, hue_default=0, sat_default=100, val_default=20) +keyboard.modules = [layers, media_keys, split] +keyboard.extensions = [rgb_ext] + # ------------------User level config variables --------------------------------------- -keyboard.leader_mode = LeaderMode.TIMEOUT keyboard.unicode_mode = UnicodeMode.LINUX keyboard.tap_time = 150 -keyboard.leader_timeout = 2000 -keyboard.debug_enabled = True -keyboard.rgb_config['num_pixels'] = 16 -keyboard.rgb_config['val_limit'] = 150 -keyboard.rgb_config['hue_step'] = 1 -keyboard.rgb_config['sat_step'] = 5 -keyboard.rgb_config['val_step'] = 5 -keyboard.rgb_config['hue_default'] = 0 -keyboard.rgb_config['sat_default'] = 100 -keyboard.rgb_config['val_default'] = 20 -keyboard.rgb_config['knight_effect_length'] = 6 -keyboard.rgb_config['animation_mode'] = 'static' -keyboard.rgb_config['animation_speed'] = 1 keyboard.debug_enabled = False LOWER = KC.TT(3)