diff --git a/.circleci/config.yml b/.circleci/config.yml index 546765c..277d605 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -22,6 +22,23 @@ jobs: paths: - .venv + test: + docker: + - image: 'python:3.7' + + environment: + KMK_TEST: 1 + PIPENV_VENV_IN_PROJECT: 1 + + steps: + - checkout + - restore_cache: + keys: + - v1-kmk-venv-{{ checksum "Pipfile.lock" }} + + - run: pip install pipenv==2018.7.1 + - run: make test + build_pyboard: docker: - image: 'python:3.7' @@ -39,7 +56,7 @@ jobs: - run: pip install pipenv==2018.7.1 - run: apt-get update && apt-get install -y gcc-arm-none-eabi gettext wget unzip - - run: make BOARD=boards/noop.py build-pyboard + - run: make SKIP_KEYMAP_VALIDATION=1 USER_KEYMAP=user_keymaps/noop.py build-pyboard build_teensy_31: docker: @@ -58,7 +75,7 @@ jobs: - run: pip install pipenv==2018.7.1 - run: apt-get update && apt-get install -y gcc-arm-none-eabi gettext wget unzip - - run: make BOARD=boards/noop.py build-teensy-3.1 + - run: make USER_KEYMAP=user_keymaps/noop.py build-teensy-3.1 workflows: version: 2 @@ -70,6 +87,14 @@ workflows: only: /.*/ tags: only: /.*/ + - test: + filters: + branches: + only: /.*/ + tags: + only: /.*/ + requires: + - lint - build_pyboard: filters: branches: @@ -77,7 +102,7 @@ workflows: tags: only: /.*/ requires: - - lint + - test - build_teensy_31: filters: branches: @@ -85,4 +110,4 @@ workflows: tags: only: /.*/ requires: - - lint + - test diff --git a/BOARD_SETUP.md b/BOARD_SETUP.md deleted file mode 100644 index b4df227..0000000 --- a/BOARD_SETUP.md +++ /dev/null @@ -1,13 +0,0 @@ -- Arch dependencies: adafruit-ampy python-dotenv wget -- Optional Arch dependencies: picocom (serial interface) -- `pip3 install --user adafruit nrfutil` -- `mkdir feather_flashing && cd feather_flashing` -- `git clone https://github.com/adafruit/Adafruit_nRF52_Bootloader.git && cd Adafruit_nRF52_Bootloader` -- `make BOARD=feather_nrf52832 VERSION=2.0.1 SERIAL=/dev/ttyUSB0 dfu-flash` (no - root req) -- `cd .. && git clone git@github.com:adafruit/circuitpython.git && cd circuitpython` -- `git submodule update --init` -- `make -C mpy-cross` -- `cd ports/nrf` -- `./drivers/bluetooth/download_ble_stack.sh` -- `make BOARD=feather_nrf52832 SERIAL=/dev/ttyUSB0 dfu-gen dfu-flash` diff --git a/Makefile b/Makefile index 11bbce9..0fddd4e 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,19 @@ lint: devdeps @pipenv run flake8 fix-isort: devdeps - @find kmk/ boards/ entrypoints/ -name "*.py" | xargs pipenv run isort + @find kmk/ user_keymaps/ -name "*.py" | xargs pipenv run isort + +test: micropython-build-unix + @echo "===> Testing keymap_sanity_check.py script" + @echo " --> Known good layout should pass..." + @MICROPYPATH=tests/test_data:./ ./bin/micropython.sh bin/keymap_sanity_check.py keymaps/known_good.py + @echo " --> Layer with ghosted MO should fail..." + @MICROPYPATH=tests/test_data:./ ./bin/micropython.sh bin/keymap_sanity_check.py keymaps/ghosted_layer_mo.py 2>/dev/null && exit 1 || exit 0 + @echo " --> Sharing a pin between rows/cols should fail..." + @MICROPYPATH=tests/test_data:./ ./bin/micropython.sh bin/keymap_sanity_check.py keymaps/duplicated_pins_between_row_col.py 2>/dev/null && exit 1 || exit 0 + @echo " --> Sharing a pin between two rows should fail..." + @MICROPYPATH=tests/test_data:./ ./bin/micropython.sh bin/keymap_sanity_check.py keymaps/duplicate_row_pins.py 2>/dev/null && exit 1 || exit 0 + @echo "===> The sanity checker is sane, unlike klardotsh" .submodules: .gitmodules @echo "===> Pulling dependencies, this may take several minutes" @@ -41,10 +53,22 @@ circuitpy-deps: .circuitpy-deps micropython-deps: .micropython-deps +vendor/micropython/ports/unix/micropython: micropython-deps vendor/micropython/ports/unix/modules/.kmk_frozen + @make -j4 -C vendor/micropython/ports/unix + +micropython-build-unix: vendor/micropython/ports/unix/micropython + freeze-nrf-vendor-deps: vendor/circuitpython/ports/nrf/freeze/.kmk_frozen freeze-teensy3.1-vendor-deps: vendor/micropython/ports/teensy/freeze/.kmk_frozen freeze-stm32-vendor-deps: vendor/micropython/ports/stm32/freeze/.kmk_frozen +vendor/micropython/ports/unix/modules/.kmk_frozen: upy-freeze.txt + @echo "===> Preparing vendored dependencies for local development" + @rm -rf vendored_libs + @mkdir -p vendored_libs + @cat $< | xargs -I '{}' cp -a {} vendor/micropython/ports/unix/modules/ + @touch $@ + vendor/circuitpython/ports/nrf/freeze/.kmk_frozen: upy-freeze.txt @echo "===> Preparing vendored dependencies for bundling" @rm -rf vendor/circuitpython/ports/nrf/freeze/* @@ -86,28 +110,28 @@ circuitpy-build-nrf: circuitpy-flash-nrf: circuitpy-build-nrf @echo "===> Flashing CircuitPython with KMK and your keymap" - @make -C vendor/circuitpython/ports/nrf BOARD=feather_nrf52832 SERIAL=${AMPY_PORT} SD=s132 FROZEN_MPY_DIR=freeze dfu-gen dfu-flash + @sudo make -C vendor/circuitpython/ports/nrf BOARD=feather_nrf52832 SERIAL=${AMPY_PORT} SD=s132 FROZEN_MPY_DIR=freeze dfu-gen dfu-flash micropython-build-teensy3.1: - @cp entrypoints/teensy31.py vendor/micropython/ports/teensy/memzip_files/main.py + #@cp entrypoints/teensy31.py vendor/micropython/ports/teensy/memzip_files/main.py @make -C vendor/micropython/ports/teensy/ BOARD=TEENSY_3.1 all micropython-flash-teensy3.1: micropython-build-teensy3.1 - @make -C vendor/micropython/ports/teensy/ BOARD=TEENSY_3.1 deploy + @sudo make -C vendor/micropython/ports/teensy/ BOARD=TEENSY_3.1 deploy micropython-build-pyboard: @make -j4 -C vendor/micropython/ports/stm32/ BOARD=PYBV11 FROZEN_MPY_DIR=freeze all micropython-flash-pyboard: micropython-build-pyboard - @make -j4 -C vendor/micropython/ports/stm32/ BOARD=PYBV11 FROZEN_MPY_DIR=freeze deploy + @sudo make -j4 -C vendor/micropython/ports/stm32/ BOARD=PYBV11 FROZEN_MPY_DIR=freeze deploy micropython-flash-pyboard-entrypoint: @echo "===> Flashing entrypoints if they doesn't already exist" @sleep 4 @-timeout -k 5s 10s pipenv run ampy -p ${AMPY_PORT} -d ${AMPY_DELAY} -b ${AMPY_BAUD} rm /flash/main.py 2>/dev/null @-timeout -k 5s 10s pipenv run ampy -p ${AMPY_PORT} -d ${AMPY_DELAY} -b ${AMPY_BAUD} rm /flash/boot.py 2>/dev/null - @-timeout -k 5s 10s pipenv run ampy -p ${AMPY_PORT} -d ${AMPY_DELAY} -b ${AMPY_BAUD} put entrypoints/pyboard.py /flash/main.py - @-timeout -k 5s 10s pipenv run ampy -p ${AMPY_PORT} -d ${AMPY_DELAY} -b ${AMPY_BAUD} put entrypoints/pyboard_boot.py /flash/boot.py + @-timeout -k 5s 10s pipenv run ampy -p ${AMPY_PORT} -d ${AMPY_DELAY} -b ${AMPY_BAUD} put kmk/entrypoints/global.py /flash/main.py + @-timeout -k 5s 10s pipenv run ampy -p ${AMPY_PORT} -d ${AMPY_DELAY} -b ${AMPY_BAUD} put kmk/entrypoints/handwire/pyboard_boot.py /flash/boot.py @echo "===> Flashed keyboard successfully!" circuitpy-flash-nrf-entrypoint: @@ -117,57 +141,64 @@ circuitpy-flash-nrf-entrypoint: @-timeout -k 5s 10s pipenv run ampy -p ${AMPY_PORT} -d ${AMPY_DELAY} -b ${AMPY_BAUD} put entrypoints/feather_nrf52832.py main.py @echo "===> Flashed keyboard successfully!" -ifndef BOARD +ifndef USER_KEYMAP build-feather-nrf52832: - @echo "===> Must provide a board (usually from boards/...) to build!" + @echo "===> Must provide a USER_KEYMAP (usually from user_keymaps/...) to build!" && exit 1 flash-feather-nrf52832: - @echo "===> Must provide a board (usually from boards/...) to build!" + @echo "===> Must provide a USER_KEYMAP (usually from user_keymaps/...) to build!" && exit 1 else build-feather-nrf52832: lint devdeps circuitpy-deps circuitpy-freeze-kmk-nrf @echo "===> Preparing keyboard script for bundling into CircuitPython" - @cp -av ${BOARD} vendor/circuitpython/ports/nrf/freeze/kmk_keyboard_user.py + @cp -av ${USER_KEYMAP} vendor/circuitpython/ports/nrf/freeze/kmk_keyboard_user.py @$(MAKE) circuitpy-build-nrf flash-feather-nrf52832: lint devdeps circuitpy-deps circuitpy-freeze-kmk-nrf @echo "===> Preparing keyboard script for bundling into CircuitPython" - @cp -av ${BOARD} vendor/circuitpython/ports/nrf/freeze/kmk_keyboard_user.py + @cp -av ${USER_KEYMAP} vendor/circuitpython/ports/nrf/freeze/kmk_keyboard_user.py @$(MAKE) circuitpy-flash-nrf circuitpy-flash-nrf-entrypoint endif -ifndef BOARD +ifndef USER_KEYMAP build-teensy-3.1: - @echo "===> Must provide a board (usually from boards/...) to build!" + @echo "===> Must provide a USER_KEYMAP (usually from user_keymaps/...) to build!" && exit 1 flash-teensy-3.1: - @echo "===> Must provide a board (usually from boards/...) to build!" + @echo "===> Must provide a USER_KEYMAP (usually from user_keymaps/...) to build!" && exit 1 else build-teensy-3.1: lint devdeps micropython-deps micropython-freeze-kmk-teensy3.1 @echo "===> Preparing keyboard script for bundling into MicroPython" - @cp -av ${BOARD} vendor/micropython/ports/teensy/freeze/kmk_keyboard_user.py + @cp -av ${USER_KEYMAP} vendor/micropython/ports/teensy/freeze/kmk_keyboard_user.py @$(MAKE) ARDUINO=${ARDUINO} micropython-build-teensy3.1 flash-teensy-3.1: lint devdeps micropython-deps micropython-freeze-kmk-teensy3.1 @echo "===> Preparing keyboard script for bundling into MicroPython" - @cp -av ${BOARD} vendor/micropython/ports/teensy/freeze/kmk_keyboard_user.py + @cp -av ${USER_KEYMAP} vendor/micropython/ports/teensy/freeze/kmk_keyboard_user.py @$(MAKE) ARDUINO=${ARDUINO} micropython-flash-teensy3.1 endif -ifndef BOARD +ifndef USER_KEYMAP build-pyboard: - @echo "===> Must provide a board (usually from boards/...) to build!" + @echo "===> Must provide a USER_KEYMAP (usually from user_keymaps/...) to build!" && exit 1 flash-pyboard: - @echo "===> Must provide a board (usually from boards/...) to build!" + @echo "===> Must provide a USER_KEYMAP (usually from user_keymaps/...) to build!" && exit 1 +else +ifndef SKIP_KEYMAP_VALIDATION +build-pyboard: lint devdeps micropython-deps micropython-freeze-kmk-stm32 micropython-build-unix else build-pyboard: lint devdeps micropython-deps micropython-freeze-kmk-stm32 +endif @echo "===> Preparing keyboard script for bundling into MicroPython" - @cp -av ${BOARD} vendor/micropython/ports/stm32/freeze/kmk_keyboard_user.py +ifndef SKIP_KEYMAP_VALIDATION + @MICROPYPATH=./ ./bin/micropython.sh bin/keymap_sanity_check.py ${USER_KEYMAP} +endif + @cp -av ${USER_KEYMAP} vendor/micropython/ports/stm32/freeze/kmk_keyboard_user.py @$(MAKE) AMPY_PORT=/dev/ttyACM0 AMPY_BAUD=115200 micropython-build-pyboard flash-pyboard: lint devdeps micropython-deps micropython-freeze-kmk-stm32 @echo "===> Preparing keyboard script for bundling into MicroPython" - @cp -av ${BOARD} vendor/micropython/ports/stm32/freeze/kmk_keyboard_user.py + @cp -av ${USER_KEYMAP} vendor/micropython/ports/stm32/freeze/kmk_keyboard_user.py @$(MAKE) AMPY_PORT=/dev/ttyACM0 AMPY_BAUD=115200 micropython-flash-pyboard micropython-flash-pyboard-entrypoint endif diff --git a/bin/keymap_sanity_check.py b/bin/keymap_sanity_check.py new file mode 100755 index 0000000..4ec5139 --- /dev/null +++ b/bin/keymap_sanity_check.py @@ -0,0 +1,70 @@ +#!/usr/bin/env micropython + +import sys + +import uos + +from kmk.common.keycodes import Keycodes + +if len(sys.argv) < 2: + print('Must provide a keymap to test as first argument', file=sys.stderr) + sys.exit(200) + +user_keymap_file = sys.argv[1] + +if user_keymap_file.endswith('.py'): + user_keymap_file = user_keymap_file[:-3] + +# Before we can import the user's keymap, we need to wrangle sys.path to +# add our stub modules. Before we can do THAT, we have to figure out where +# we actually are, and that's not the most trivial thing in MicroPython! +# +# The hack here is to see if we can find ourselves in whatever uPy thinks +# the current directory is. If we can, we need to head up a level. Obviously, +# if the layout of the KMK repo ever changes, this script will need updated +# or all hell will break loose. + +# First, hack around https://github.com/micropython/micropython/issues/2322, +# where frozen modules aren't available if MicroPython is running a script +# rather than via REPL +sys.path.insert(0, '') + +if any(fname == 'keymap_sanity_check.py' for fname, _, _ in uos.ilistdir()): + sys.path.extend(('../', '../upy-unix-stubs/')) +else: + sys.path.extend(('./', './upy-unix-stubs')) + +user_keymap = __import__(user_keymap_file) + +if hasattr(user_keymap, 'cols') or hasattr(user_keymap, 'rows'): + assert hasattr(user_keymap, 'cols'), 'Handwired keyboards must have both rows and cols defined' + assert hasattr(user_keymap, 'rows'), 'Handwired keyboards must have both rows and cols defined' + + # Ensure that no pins are duplicated in a handwire config + # This is the same check done in the MatrixScanners, relying + # on the __repr__ of the objects to be unique (because generally, + # Pin objects themselves are not hashable) + assert len(user_keymap.cols) == len({p for p in user_keymap.cols}), \ + 'Cannot use a single pin for multiple columns' + assert len(user_keymap.rows) == len({p for p in user_keymap.rows}), \ + 'Cannot use a single pin for multiple rows' + + unique_pins = {repr(c) for c in user_keymap.cols} | {repr(r) for r in user_keymap.rows} + assert len(unique_pins) == len(user_keymap.cols) + len(user_keymap.rows), \ + 'Cannot use a pin as both a column and row' + +assert hasattr(user_keymap, 'keymap'), 'Must define a keymap array' +assert len(user_keymap.keymap), 'Keymap must contain at least one layer' + +for lidx, layer in enumerate(user_keymap.keymap): + assert len(layer), 'Layer {} must contain at least one row'.format(lidx) + assert all(len(row) for row in layer), 'Layer {} must not contain empty rows'.format(lidx) + assert all(len(row) == len(layer[0]) for row in user_keymap.keymap), \ + 'All rows in layer {} must be of the same length'.format(lidx) + + for ridx, row in enumerate(layer): + for cidx, key in enumerate(row): + if key.code == Keycodes.Layers._KC_MO: + assert user_keymap.keymap[key.layer][ridx][cidx] == Keycodes.KMK.KC_TRNS, \ + ('The physical key used for MO layer switching must be KC_TRNS on the ' + 'target layer or you will get stuck on that layer.') diff --git a/bin/micropython.sh b/bin/micropython.sh new file mode 100755 index 0000000..3854508 --- /dev/null +++ b/bin/micropython.sh @@ -0,0 +1,6 @@ +if [ ! -f vendor/micropython/ports/unix/micropython ]; then + echo "Run make micropython-build-unix" + exit 1 +fi + +vendor/micropython/ports/unix/micropython $@ diff --git a/boards/kdb424/handwire_planck_pyboard.py b/boards/kdb424/handwire_planck_pyboard.py deleted file mode 100644 index 79bfd10..0000000 --- a/boards/kdb424/handwire_planck_pyboard.py +++ /dev/null @@ -1,44 +0,0 @@ -# flake8: noqa -from logging import DEBUG - -import machine - -from kmk.common.consts import DiodeOrientation -from kmk.common.keycodes import KC -from kmk.firmware import Firmware -from kmk.micropython.pyb_hid import HIDHelper - - -def main(): - p = machine.Pin.board - - cols = (p.Y12, p.Y11, p.Y10, p.Y9, p.X8, p.X7, p.X6, p.X5, p.X4, p.X3, p.X2, p.X1) - rows = (p.Y1, p.Y2, p.Y3, p.Y4) - - diode_orientation = DiodeOrientation.COLUMNS - - keymap = [ - [ - [KC.ESC, 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.CTRL, KC.GUI, KC.ALT, KC.RESET, KC.MO(1), KC.SPC, KC.SPC, KC.A, KC.LEFT, KC.DOWN, KC.UP, KC.RIGHT], - ], - [ - [KC.A, KC.QUOTE, KC.COMMA, KC.DOT, KC.P, KC.Y, KC.F, KC.G, KC.C, KC.R, KC.L, KC.BACKSPACE], - [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.SCOLON, KC.Q, KC.J, KC.K, KC.X, KC.B, KC.M, KC.W, KC.V, KC.Z, KC.SLSH], - [KC.CTRL, KC.GUI, KC.ALT, KC.RESET, KC.MO(1), KC.SPC, KC.SPC, KC.A, KC.LEFT, KC.DOWN, KC.UP, KC.RIGHT], - ], - ] - - firmware = Firmware( - keymap=keymap, - row_pins=rows, - col_pins=cols, - diode_orientation=diode_orientation, - hid=HIDHelper, - log_level=DEBUG, - ) - - firmware.go() diff --git a/boards/klardotsh/threethree_matrix_pyboard.py b/boards/klardotsh/threethree_matrix_pyboard.py deleted file mode 100644 index a7af387..0000000 --- a/boards/klardotsh/threethree_matrix_pyboard.py +++ /dev/null @@ -1,46 +0,0 @@ -from logging import DEBUG - -import machine - -from kmk.common.consts import DiodeOrientation -from kmk.common.keycodes import KC -from kmk.firmware import Firmware -from kmk.micropython.pyb_hid import HIDHelper - - -def main(): - p = machine.Pin.board - - cols = (p.X10, p.X11, p.X12) - rows = (p.X1, p.X2, p.X3) - - diode_orientation = DiodeOrientation.COLUMNS - - keymap = [ - [ - [KC.MO(1), KC.H, KC.RESET], - [KC.MO(2), KC.I, KC.ENTER], - [KC.LCTRL, KC.SPACE, KC.LSHIFT], - ], - [ - [KC.TRNS, KC.B, KC.C], - [KC.NO, KC.D, KC.E], - [KC.F, KC.G, KC.H], - ], - [ - [KC.X, KC.Y, KC.Z], - [KC.TRNS, KC.N, KC.O], - [KC.R, KC.P, KC.Q], - ], - ] - - firmware = Firmware( - keymap=keymap, - row_pins=rows, - col_pins=cols, - diode_orientation=diode_orientation, - hid=HIDHelper, - log_level=DEBUG, - ) - - firmware.go() diff --git a/boards/klardotsh/twotwo_matrix_feather.py b/boards/klardotsh/twotwo_matrix_feather.py deleted file mode 100644 index 9a814c8..0000000 --- a/boards/klardotsh/twotwo_matrix_feather.py +++ /dev/null @@ -1,28 +0,0 @@ -from logging import DEBUG - -import board - -from kmk.common.consts import DiodeOrientation -from kmk.firmware import Firmware - - -def main(): - cols = (board.A4, board.A5) - rows = (board.D27, board.A6) - - diode_orientation = DiodeOrientation.COLUMNS - - keymap = [ - ['A', 'B'], - ['C', 'D'], - ] - - firmware = Firmware( - keymap=keymap, - row_pins=rows, - col_pins=cols, - diode_orientation=diode_orientation, - log_level=DEBUG, - ) - - firmware.go() diff --git a/entrypoints/feather_nrf52832.py b/entrypoints/feather_nrf52832.py deleted file mode 100644 index a21b146..0000000 --- a/entrypoints/feather_nrf52832.py +++ /dev/null @@ -1,12 +0,0 @@ -import sys - -from kmk.circuitpython.util import feather_red_led_flash -from kmk_keyboard_user import main - -if __name__ == '__main__': - try: - main() - except Exception as e: - sys.print_exception(e) - feather_red_led_flash(duration=10, rate=0.5) - sys.exit(1) diff --git a/entrypoints/pyboard.py b/entrypoints/pyboard.py deleted file mode 100644 index 31df713..0000000 --- a/entrypoints/pyboard.py +++ /dev/null @@ -1,10 +0,0 @@ -import sys - -from kmk_keyboard_user import main - -if __name__ == '__main__': - try: - main() - except Exception as e: - sys.print_exception(e) - sys.exit(1) diff --git a/entrypoints/teensy31.py b/entrypoints/teensy31.py deleted file mode 100644 index 31df713..0000000 --- a/entrypoints/teensy31.py +++ /dev/null @@ -1,10 +0,0 @@ -import sys - -from kmk_keyboard_user import main - -if __name__ == '__main__': - try: - main() - except Exception as e: - sys.print_exception(e) - sys.exit(1) diff --git a/kmk/entrypoints/__init__.py b/kmk/entrypoints/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/kmk/entrypoints/global.py b/kmk/entrypoints/global.py new file mode 100644 index 0000000..c07d83c --- /dev/null +++ b/kmk/entrypoints/global.py @@ -0,0 +1,4 @@ +from kmk_keyboard_user import main + +if __name__ == '__main__': + main() diff --git a/kmk/entrypoints/handwire/__init__.py b/kmk/entrypoints/handwire/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/kmk/entrypoints/handwire/pyboard.py b/kmk/entrypoints/handwire/pyboard.py new file mode 100644 index 0000000..0a0f582 --- /dev/null +++ b/kmk/entrypoints/handwire/pyboard.py @@ -0,0 +1,24 @@ +import sys +from logging import DEBUG + +from kmk.firmware import Firmware +from kmk.micropython.pyb_hid import HIDHelper + + +def main(): + from kmk_keyboard_user import cols, diode_orientation, keymap, rows + + try: + firmware = Firmware( + keymap=keymap, + row_pins=rows, + col_pins=cols, + diode_orientation=diode_orientation, + hid=HIDHelper, + log_level=DEBUG, + ) + + firmware.go() + except Exception as e: + sys.print_exception(e) + sys.exit(1) diff --git a/entrypoints/pyboard_boot.py b/kmk/entrypoints/handwire/pyboard_boot.py similarity index 100% rename from entrypoints/pyboard_boot.py rename to kmk/entrypoints/handwire/pyboard_boot.py diff --git a/setup.cfg b/setup.cfg index 0c75357..48a6b8c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -3,7 +3,8 @@ exclude = .git,__pycache__,vendor,.venv max_line_length = 99 ignore = X100 per-file-ignores = - boards/**/*.py: E501 + user_keymaps/**/*.py: F401,E501 + tests/test_data/keymaps/**/*.py: F401,E501 [isort] -known_third_party = analogio,bitbangio,bleio,board,busio,digitalio,framebuf,gamepad,gc,microcontroller,micropython,pulseio,pyb,pydux,uio,ubluepy,machine,pyb +known_third_party = analogio,bitbangio,bleio,board,busio,digitalio,framebuf,gamepad,gc,microcontroller,micropython,pulseio,pyb,pydux,uio,ubluepy,machine,pyb,uos diff --git a/tests/test_data/__init__.py b/tests/test_data/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_data/keymaps/__init__.py b/tests/test_data/keymaps/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_data/keymaps/duplicate_row_pins.py b/tests/test_data/keymaps/duplicate_row_pins.py new file mode 100644 index 0000000..aea8f23 --- /dev/null +++ b/tests/test_data/keymaps/duplicate_row_pins.py @@ -0,0 +1,29 @@ +import machine + +from kmk.common.consts import DiodeOrientation +from kmk.common.keycodes import KC +from kmk.entrypoints.handwire.pyboard import main + +p = machine.Pin.board +cols = (p.X10, p.X10, p.X12) +rows = (p.X1, p.X2, p.X3) + +diode_orientation = DiodeOrientation.COLUMNS + +keymap = [ + [ + [KC.MO(1), KC.H, KC.RESET], + [KC.MO(2), KC.I, KC.ENTER], + [KC.LCTRL, KC.SPACE, KC.LSHIFT], + ], + [ + [KC.TRNS, KC.B, KC.C], + [KC.NO, KC.D, KC.E], + [KC.F, KC.G, KC.H], + ], + [ + [KC.X, KC.Y, KC.Z], + [KC.TRNS, KC.N, KC.O], + [KC.R, KC.P, KC.Q], + ], +] diff --git a/tests/test_data/keymaps/duplicated_pins_between_row_col.py b/tests/test_data/keymaps/duplicated_pins_between_row_col.py new file mode 100644 index 0000000..25624e6 --- /dev/null +++ b/tests/test_data/keymaps/duplicated_pins_between_row_col.py @@ -0,0 +1,29 @@ +import machine + +from kmk.common.consts import DiodeOrientation +from kmk.common.keycodes import KC +from kmk.entrypoints.handwire.pyboard import main + +p = machine.Pin.board +cols = (p.X10, p.X11, p.X12) +rows = (p.X1, p.X11, p.X3) + +diode_orientation = DiodeOrientation.COLUMNS + +keymap = [ + [ + [KC.MO(1), KC.H, KC.RESET], + [KC.MO(2), KC.I, KC.ENTER], + [KC.LCTRL, KC.SPACE, KC.LSHIFT], + ], + [ + [KC.TRNS, KC.B, KC.C], + [KC.NO, KC.D, KC.E], + [KC.F, KC.G, KC.H], + ], + [ + [KC.X, KC.Y, KC.Z], + [KC.TRNS, KC.N, KC.O], + [KC.R, KC.P, KC.Q], + ], +] diff --git a/tests/test_data/keymaps/ghosted_layer_mo.py b/tests/test_data/keymaps/ghosted_layer_mo.py new file mode 100644 index 0000000..658f838 --- /dev/null +++ b/tests/test_data/keymaps/ghosted_layer_mo.py @@ -0,0 +1,29 @@ +import machine + +from kmk.common.consts import DiodeOrientation +from kmk.common.keycodes import KC +from kmk.entrypoints.handwire.pyboard import main + +p = machine.Pin.board +cols = (p.X10, p.X11, p.X12) +rows = (p.X1, p.X2, p.X3) + +diode_orientation = DiodeOrientation.COLUMNS + +keymap = [ + [ + [KC.MO(1), KC.H, KC.RESET], + [KC.MO(2), KC.I, KC.ENTER], + [KC.LCTRL, KC.SPACE, KC.LSHIFT], + ], + [ + [KC.A, KC.B, KC.C], + [KC.NO, KC.D, KC.E], + [KC.F, KC.G, KC.H], + ], + [ + [KC.X, KC.Y, KC.Z], + [KC.TRNS, KC.N, KC.O], + [KC.R, KC.P, KC.Q], + ], +] diff --git a/tests/test_data/keymaps/known_good.py b/tests/test_data/keymaps/known_good.py new file mode 100644 index 0000000..f95d0db --- /dev/null +++ b/tests/test_data/keymaps/known_good.py @@ -0,0 +1,29 @@ +import machine + +from kmk.common.consts import DiodeOrientation +from kmk.common.keycodes import KC +from kmk.entrypoints.handwire.pyboard import main + +p = machine.Pin.board +cols = (p.X10, p.X11, p.X12) +rows = (p.X1, p.X2, p.X3) + +diode_orientation = DiodeOrientation.COLUMNS + +keymap = [ + [ + [KC.MO(1), KC.H, KC.RESET], + [KC.MO(2), KC.I, KC.ENTER], + [KC.LCTRL, KC.SPACE, KC.LSHIFT], + ], + [ + [KC.TRNS, KC.B, KC.C], + [KC.NO, KC.D, KC.E], + [KC.F, KC.G, KC.H], + ], + [ + [KC.X, KC.Y, KC.Z], + [KC.TRNS, KC.N, KC.O], + [KC.R, KC.P, KC.Q], + ], +] diff --git a/upy-unix-stubs/machine/__init__.py b/upy-unix-stubs/machine/__init__.py new file mode 100644 index 0000000..ecf74c1 --- /dev/null +++ b/upy-unix-stubs/machine/__init__.py @@ -0,0 +1,18 @@ +class Anything: + ''' + A stub class which will repr as a provided name + ''' + def __init__(self, name): + self.name = name + + def __repr__(self): + return 'Anything<{}>'.format(self.name) + + +class Passthrough: + def __getattr__(self, attr): + return Anything(attr) + + +class Pin: + board = Passthrough() diff --git a/upy-unix-stubs/pyb/USB_HID.py b/upy-unix-stubs/pyb/USB_HID.py new file mode 100644 index 0000000..e69de29 diff --git a/upy-unix-stubs/pyb/__init__.py b/upy-unix-stubs/pyb/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/upy-unix-stubs/pyb/delay.py b/upy-unix-stubs/pyb/delay.py new file mode 100644 index 0000000..e69de29 diff --git a/user_keymaps/__init__.py b/user_keymaps/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/user_keymaps/kdb424/__init__.py b/user_keymaps/kdb424/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/user_keymaps/kdb424/handwire_planck_pyboard.py b/user_keymaps/kdb424/handwire_planck_pyboard.py new file mode 100644 index 0000000..cb1ee23 --- /dev/null +++ b/user_keymaps/kdb424/handwire_planck_pyboard.py @@ -0,0 +1,27 @@ +import machine + +from kmk.common.consts import DiodeOrientation +from kmk.common.keycodes import KC +from kmk.micropython.pyb_hid import HIDHelper + +p = machine.Pin.board + +cols = (p.Y12, p.Y11, p.Y10, p.Y9, p.X8, p.X7, p.X6, p.X5, p.X4, p.X3, p.X2, p.X1) +rows = (p.Y1, p.Y2, p.Y3, p.Y4) + +diode_orientation = DiodeOrientation.COLUMNS + +keymap = [ + [ + [KC.ESC, 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.RESET, KC.MO(1), KC.SPC, KC.SPC, KC.A, KC.LEFT, KC.DOWN, KC.UP, KC.RIGHT], + ], + [ + [KC.A, KC.QUOTE, KC.COMMA, KC.DOT, KC.P, KC.Y, KC.F, KC.G, KC.C, KC.R, KC.L, KC.BACKSPACE], + [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.SCOLON, 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.RESET, KC.TRNS, KC.SPC, KC.SPC, KC.A, KC.LEFT, KC.DOWN, KC.UP, KC.RIGHT], + ], +] diff --git a/user_keymaps/klardotsh/__init__.py b/user_keymaps/klardotsh/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/user_keymaps/klardotsh/threethree_matrix_pyboard.py b/user_keymaps/klardotsh/threethree_matrix_pyboard.py new file mode 100644 index 0000000..f95d0db --- /dev/null +++ b/user_keymaps/klardotsh/threethree_matrix_pyboard.py @@ -0,0 +1,29 @@ +import machine + +from kmk.common.consts import DiodeOrientation +from kmk.common.keycodes import KC +from kmk.entrypoints.handwire.pyboard import main + +p = machine.Pin.board +cols = (p.X10, p.X11, p.X12) +rows = (p.X1, p.X2, p.X3) + +diode_orientation = DiodeOrientation.COLUMNS + +keymap = [ + [ + [KC.MO(1), KC.H, KC.RESET], + [KC.MO(2), KC.I, KC.ENTER], + [KC.LCTRL, KC.SPACE, KC.LSHIFT], + ], + [ + [KC.TRNS, KC.B, KC.C], + [KC.NO, KC.D, KC.E], + [KC.F, KC.G, KC.H], + ], + [ + [KC.X, KC.Y, KC.Z], + [KC.TRNS, KC.N, KC.O], + [KC.R, KC.P, KC.Q], + ], +] diff --git a/boards/noop.py b/user_keymaps/noop.py similarity index 100% rename from boards/noop.py rename to user_keymaps/noop.py