diff --git a/Makefile b/Makefile index 1304894..eba91c9 100644 --- a/Makefile +++ b/Makefile @@ -6,9 +6,9 @@ freeze-nrf-vendor-deps \ lint -NRF_DFU_PORT ?= /dev/ttyUSB0 -NRF_DFU_BAUD ?= 115200 -NRF_DFU_DELAY ?= 1.5 +AMPY_PORT ?= /dev/ttyUSB0 +AMPY_BAUD ?= 115200 +AMPY_DELAY ?= 1.5 ARDUINO ?= /usr/share/arduino devdeps: Pipfile.lock @@ -39,8 +39,8 @@ circuitpy-deps: .circuitpy-deps micropython-deps: .micropython-deps 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/circuitpython/ports/nrf/freeze/.kmk_frozen: upy-freeze.txt @echo "===> Preparing vendored dependencies for bundling" @@ -55,6 +55,13 @@ vendor/micropython/ports/teensy/freeze/.kmk_frozen: upy-freeze.txt @cat $< | xargs -I '{}' cp -a {} vendor/micropython/ports/teensy/freeze/ @touch $@ +vendor/micropython/ports/stm32/freeze/.kmk_frozen: upy-freeze.txt + @echo "===> Preparing vendored dependencies for bundling" + @mkdir vendor/micropython/ports/stm32/freeze/ + @rm -rf vendor/micropython/ports/stm32/freeze/* + @cat $< | xargs -I '{}' cp -a {} vendor/micropython/ports/stm32/freeze/ + @touch $@ + circuitpy-freeze-kmk-nrf: freeze-nrf-vendor-deps @echo "===> Preparing KMK source for bundling into CircuitPython" @rm -rf vendor/circuitpython/ports/nrf/kmk* @@ -65,19 +72,38 @@ micropython-freeze-kmk-teensy3.1: freeze-teensy3.1-vendor-deps @rm -rf vendor/micropython/ports/teensy/kmk* @cp -av kmk vendor/micropython/ports/teensy/memzip_files/ +micropython-freeze-kmk-stm32: freeze-stm32-vendor-deps + @echo "===> Preparing KMK source for bundling into MicroPython" + @rm -rf vendor/micropython/ports/stm32/freeze/kmk* + @cp -av kmk vendor/micropython/ports/stm32/freeze/ + circuitpy-flash-nrf: @echo "===> Building and flashing CircuitPython with KMK and your keymap" - @make -C vendor/circuitpython/ports/nrf BOARD=feather_nrf52832 SERIAL=${NRF_DFU_PORT} SD=s132 FROZEN_MPY_DIR=freeze clean dfu-gen dfu-flash + @make -C vendor/circuitpython/ports/nrf BOARD=feather_nrf52832 SERIAL=${AMPY_PORT} SD=s132 FROZEN_MPY_DIR=freeze clean dfu-gen dfu-flash micropython-flash-teensy3.1: @cp entrypoints/teensy31.py vendor/micropython/ports/teensy/memzip_files/main.py @make -C vendor/micropython/ports/teensy/ BOARD=TEENSY_3.1 deploy +micropython-flash-pyboard: + @make -j4 -C vendor/micropython/ports/stm32/ BOARD=PYBV11 clean + @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} reset + @echo "===> Flashed keyboard successfully!" + circuitpy-flash-nrf-entrypoint: @echo "===> Flashing entrypoint if it doesn't already exist" @sleep 2 - @-timeout -k 5s 10s pipenv run ampy -p ${NRF_DFU_PORT} -d ${NRF_DFU_DELAY} -b ${NRF_DFU_BAUD} rm main.py 2>/dev/null - @-timeout -k 5s 10s pipenv run ampy -p ${NRF_DFU_PORT} -d ${NRF_DFU_DELAY} -b ${NRF_DFU_BAUD} put entrypoints/feather_nrf52832.py main.py + @-timeout -k 5s 10s pipenv run ampy -p ${AMPY_PORT} -d ${AMPY_DELAY} -b ${AMPY_BAUD} rm main.py 2>/dev/null + @-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 @@ -100,6 +126,16 @@ build-teensy-3.1: lint devdeps micropython-deps micropython-freeze-kmk-teensy3.1 @$(MAKE) ARDUINO=${ARDUINO} micropython-flash-teensy3.1 endif +ifndef BOARD +build-pyboard: + @echo "===> Must provide a board (usually from boards/...) to build!" +else +build-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 + @$(MAKE) AMPY_PORT=/dev/ttyACM0 AMPY_BAUD=115200 micropython-flash-pyboard micropython-flash-pyboard-entrypoint +endif + # Fully wipe the board with only stock CircuitPython burn-it-all-with-fire: lint devdeps @echo "===> Flashing STOCK CircuitPython with no KMK or user keyboard scripts, and wiping entrypoint" @@ -117,5 +153,5 @@ burn-it-all-with-fire: lint devdeps @$(MAKE) circuitpy-flash-nrf @echo "===> Wiping keyboard config" @sleep 2 - @-timeout -k 5s 10s pipenv run ampy -p ${NRF_DFU_PORT} -d ${NRF_DFU_DELAY} -b ${NRF_DFU_BAUD} rm main.py 2>/dev/null + @-timeout -k 5s 10s pipenv run ampy -p ${AMPY_PORT} -d ${AMPY_DELAY} -b ${AMPY_BAUD} rm main.py 2>/dev/null @echo "===> Wiped! Probably safe to flash keyboard, try Python serial REPL to verify?" diff --git a/boards/klardotsh/threethree_matrix_pyboard.py b/boards/klardotsh/threethree_matrix_pyboard.py new file mode 100644 index 0000000..d0b767b --- /dev/null +++ b/boards/klardotsh/threethree_matrix_pyboard.py @@ -0,0 +1,27 @@ +from logging import DEBUG + +from kmk.common.consts import DiodeOrientation +from kmk.firmware import Firmware + + +def main(): + cols = ('X10', 'X11', 'X12') + rows = ('X1', 'X2', 'X3') + + diode_orientation = DiodeOrientation.COLUMNS + + keymap = [ + ['A', 'B', 'C'], + ['D', 'E', 'F'], + ['G', 'H', 'I'], + ] + + firmware = Firmware( + keymap=keymap, + row_pins=rows, + col_pins=cols, + diode_orientation=diode_orientation, + log_level=DEBUG, + ) + + firmware.go() diff --git a/entrypoints/pyboard.py b/entrypoints/pyboard.py new file mode 100644 index 0000000..31df713 --- /dev/null +++ b/entrypoints/pyboard.py @@ -0,0 +1,10 @@ +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/pyboard_boot.py b/entrypoints/pyboard_boot.py new file mode 100644 index 0000000..46695ae --- /dev/null +++ b/entrypoints/pyboard_boot.py @@ -0,0 +1,3 @@ +import pyb + +pyb.usb_mode('VCP+HID') # act as a serial device and a mouse diff --git a/kmk/micropython/matrix.py b/kmk/micropython/matrix.py new file mode 100644 index 0000000..e7c329b --- /dev/null +++ b/kmk/micropython/matrix.py @@ -0,0 +1,49 @@ +import machine + +from kmk.common.abstract.matrix_scanner import AbstractMatrixScanner +from kmk.common.consts import DiodeOrientation + + +class MatrixScanner(AbstractMatrixScanner): + def __init__(self, cols, rows, diode_orientation=DiodeOrientation.COLUMNS): + # A pin cannot be both a row and column, detect this by combining the + # two tuples into a set and validating that the length did not drop + unique_pins = set(cols) | set(rows) + if len(unique_pins) != len(cols) + len(rows): + raise ValueError('Cannot use a pin as both a column and row') + + self.cols = [machine.Pin(pin) for pin in cols] + self.rows = [machine.Pin(pin) for pin in rows] + self.diode_orientation = diode_orientation + + if self.diode_orientation == DiodeOrientation.COLUMNS: + self.outputs = self.cols + self.inputs = self.rows + elif self.diode_orientation == DiodeOrientation.ROWS: + self.outputs = self.rows + self.inputs = self.cols + else: + raise ValueError('Invalid DiodeOrientation: {}'.format( + self.diode_orientation, + )) + + for pin in self.outputs: + pin.init(machine.Pin.OUT) + pin.off() + + for pin in self.inputs: + pin.init(machine.Pin.IN, machine.Pin.PULL_DOWN) + pin.off() + + def _normalize_matrix(self, matrix): + return super()._normalize_matrix(matrix) + + def raw_scan(self): + matrix = [] + + for opin in self.outputs: + opin.value(1) + matrix.append([bool(ipin.value()) for ipin in self.inputs]) + opin.value(0) + + return self._normalize_matrix(matrix) diff --git a/setup.cfg b/setup.cfg index 76c6b0c..02f98c8 100644 --- a/setup.cfg +++ b/setup.cfg @@ -3,4 +3,4 @@ exclude = .git,__pycache__,vendor,.venv max_line_length = 99 [isort] -known_third_party = analogio,bitbangio,bleio,board,busio,digitalio,framebuf,gamepad,gc,microcontroller,micropython,pulseio,pyb,pydux,uio,ubluepy +known_third_party = analogio,bitbangio,bleio,board,busio,digitalio,framebuf,gamepad,gc,microcontroller,micropython,pulseio,pyb,pydux,uio,ubluepy,machine,pyb