Compare commits
1 Commits
mpy_build
...
enhancemen
Author | SHA1 | Date | |
---|---|---|---|
|
490e94e4e3 |
23
.github/workflows/build.yml
vendored
23
.github/workflows/build.yml
vendored
@@ -1,23 +0,0 @@
|
|||||||
name: build_mpy
|
|
||||||
on: [push]
|
|
||||||
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
name: Build
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: run build script
|
|
||||||
run: ./docker_mpy_build.sh
|
|
||||||
|
|
||||||
- name: look
|
|
||||||
run: ls -la compiled/
|
|
||||||
|
|
||||||
- name: Archive
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: mpy
|
|
||||||
path: compiled
|
|
37
Dockerfile
37
Dockerfile
@@ -1,20 +1,39 @@
|
|||||||
FROM python:3.9-slim-buster
|
FROM python:3.9-slim-buster
|
||||||
|
|
||||||
|
ARG KMKPY_REF
|
||||||
|
ARG KMKPY_URL
|
||||||
|
|
||||||
|
ENV KMKPY_REF ${KMKPY_REF}
|
||||||
|
ENV KMKPY_URL ${KMKPY_URL}
|
||||||
|
|
||||||
RUN mkdir -p /app /dist
|
RUN mkdir -p /app /dist
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y curl
|
RUN apt-get update && apt-get install -y build-essential curl gettext git git-lfs rsync wget zip lbzip2
|
||||||
|
RUN pip install pipenv
|
||||||
|
|
||||||
RUN curl https://adafruit-circuit-python.s3.amazonaws.com/bin/mpy-cross/linux-amd64/mpy-cross.static-amd64-linux-8.0.0 --output mpy-cross-8
|
# Pull CircuitPython-designated ARM GCC to avoid mismatches/weird
|
||||||
RUN curl https://adafruit-circuit-python.s3.amazonaws.com/bin/mpy-cross/linux-amd64/mpy-cross.static-amd64-linux-7.0.0 --output mpy-cross-7
|
# inconsistencies with upstream
|
||||||
|
RUN curl -L -o /tmp/gcc-arm.tar.bz2 https://adafruit-circuit-python.s3.amazonaws.com/gcc-arm-none-eabi-9-2019-q4-major-x86_64-linux.tar.bz2 && \
|
||||||
|
tar -C /usr --strip-components=1 -xaf /tmp/gcc-arm.tar.bz2 && \
|
||||||
|
rm -rf /tmp/gcc-arm.tar.bz2
|
||||||
|
|
||||||
|
# Get a local copy of KMKPython and its dependencies. We don't provide MPY
|
||||||
|
# builds for kmkpython anymore, so we can get away with being opinionated
|
||||||
|
# here.
|
||||||
|
RUN git init /opt/kmkpython && \
|
||||||
|
git -C /opt/kmkpython remote add origin ${KMKPY_URL} && \
|
||||||
|
git -C /opt/kmkpython fetch --depth 1 origin ${KMKPY_REF} && \
|
||||||
|
git -C /opt/kmkpython checkout FETCH_HEAD && \
|
||||||
|
git -C /opt/kmkpython submodule update --init --recursive
|
||||||
|
|
||||||
RUN chmod +x mpy-cross-8
|
# Build the MPY compiler
|
||||||
|
RUN make -C /opt/kmkpython/mpy-cross
|
||||||
|
|
||||||
RUN chmod +x mpy-cross-7
|
ENV PATH=/opt/kmkpython/mpy-cross:${PATH}
|
||||||
|
|
||||||
|
RUN mkdir -p /opt/kmkpython/frozen/kmk/kmk
|
||||||
|
COPY ./build_kmkpython_release.sh /app/
|
||||||
|
COPY ./kmk /opt/kmkpython/frozen/kmk/kmk
|
||||||
|
|
||||||
COPY ./docker_mpy_build.sh /app/build.sh
|
CMD /app/build_kmkpython_release.sh
|
||||||
# COPY ./kmk /app/kmk/
|
|
||||||
|
|
||||||
CMD ["bash", "build.sh"]
|
|
||||||
|
2
Makefile
2
Makefile
@@ -92,7 +92,7 @@ test: lint unit-tests
|
|||||||
|
|
||||||
.PHONY: unit-tests
|
.PHONY: unit-tests
|
||||||
unit-tests: devdeps
|
unit-tests: devdeps
|
||||||
@$(PIPENV) run python3 -m unittest
|
@$(PIPENV) run python3 -m unittest ${TESTS}
|
||||||
|
|
||||||
reset-bootloader:
|
reset-bootloader:
|
||||||
@echo "===> Rebooting your board to bootloader (safe to ignore file not found errors)"
|
@echo "===> Rebooting your board to bootloader (safe to ignore file not found errors)"
|
||||||
|
@@ -15,7 +15,6 @@ knob.extensions.append(media_keys)
|
|||||||
|
|
||||||
# Rotary encoder that also acts as a key
|
# Rotary encoder that also acts as a key
|
||||||
encoder_handler = EncoderHandler()
|
encoder_handler = EncoderHandler()
|
||||||
encoder_handler.divisor = 2
|
|
||||||
encoder_handler.pins = ((board.D1, board.D2, board.D0),)
|
encoder_handler.pins = ((board.D1, board.D2, board.D0),)
|
||||||
encoder_handler.map = (((KC.VOLD, KC.VOLU, KC.MUTE),),)
|
encoder_handler.map = (((KC.VOLD, KC.VOLU, KC.MUTE),),)
|
||||||
knob.modules.append(encoder_handler)
|
knob.modules.append(encoder_handler)
|
||||||
|
@@ -15,7 +15,6 @@ knob.extensions.append(media_keys)
|
|||||||
|
|
||||||
# Rotary encoders that also acts as keys
|
# Rotary encoders that also acts as keys
|
||||||
encoder_handler = EncoderHandler()
|
encoder_handler = EncoderHandler()
|
||||||
encoder_handler.divisor = 2
|
|
||||||
encoder_handler.pins = (
|
encoder_handler.pins = (
|
||||||
(board.D1, board.D2, board.D0),
|
(board.D1, board.D2, board.D0),
|
||||||
(board.D9, board.D10, board.D3),
|
(board.D9, board.D10, board.D3),
|
||||||
|
@@ -78,7 +78,6 @@ keyboard.keymap = [
|
|||||||
|
|
||||||
# Rotary encoder that also acts as a key
|
# Rotary encoder that also acts as a key
|
||||||
encoder_handler = EncoderHandler()
|
encoder_handler = EncoderHandler()
|
||||||
encoder_handler.divisor = 2
|
|
||||||
encoder_handler.pins = ((board.D8, board.D7, board.D9),)
|
encoder_handler.pins = ((board.D8, board.D7, board.D9),)
|
||||||
encoder_handler.map = (((KC.VOLD, KC.VOLU, KC.MUTE),),)
|
encoder_handler.map = (((KC.VOLD, KC.VOLU, KC.MUTE),),)
|
||||||
keyboard.modules.append(encoder_handler)
|
keyboard.modules.append(encoder_handler)
|
||||||
|
@@ -1,7 +0,0 @@
|
|||||||
version: '3.3'
|
|
||||||
services:
|
|
||||||
mpy_kmk:
|
|
||||||
build: .
|
|
||||||
volumes:
|
|
||||||
- ./kmk:/app/kmk
|
|
||||||
- ./.compiled:/app/compiled
|
|
@@ -1,14 +0,0 @@
|
|||||||
|
|
||||||
#!/bin/sh
|
|
||||||
echo "building mpy"
|
|
||||||
echo $(ls compiled)
|
|
||||||
|
|
||||||
find kmk/ -name "*.py" -exec sh -c 'mkdir -p compiled/8/$(dirname {}) &&\
|
|
||||||
./mpy-cross-8 -O2 {} -o compiled/8/$(dirname {})/$(basename -s .py {}).mpy' \;
|
|
||||||
|
|
||||||
find kmk/ -name "*.py" -exec sh -c 'mkdir -p compiled/7/$(dirname {}) &&\
|
|
||||||
./mpy-cross-7 -O2 {} -o compiled/7/$(dirname {})/$(basename -s .py {}).mpy' \;
|
|
||||||
|
|
||||||
echo $(ls compiled)
|
|
||||||
|
|
||||||
echo "done building"
|
|
@@ -27,7 +27,9 @@ to Black formatting as documented in `pyproject.toml`)
|
|||||||
Unit tests within the `tests` folder mock various CircuitPython modules to allow
|
Unit tests within the `tests` folder mock various CircuitPython modules to allow
|
||||||
them to be executed in a desktop development environment.
|
them to be executed in a desktop development environment.
|
||||||
|
|
||||||
Execute tests using the command `python -m unittest`.
|
Execute tests using the command `make unit-tests`. The `unit-tests` target
|
||||||
|
accepts an additional environment variable for selection of specific tests,
|
||||||
|
example `make unit-tests TESTS="tests.test_kmk_keys tests.test_layers"`.
|
||||||
|
|
||||||
## Contributing Documentation
|
## Contributing Documentation
|
||||||
While KMK welcomes documentation from anyone with and understanding of the issues
|
While KMK welcomes documentation from anyone with and understanding of the issues
|
||||||
|
@@ -127,13 +127,3 @@ def ble_refresh(key, keyboard, *args, **kwargs):
|
|||||||
keyboard._hid_helper.stop_advertising()
|
keyboard._hid_helper.stop_advertising()
|
||||||
keyboard._hid_helper.start_advertising()
|
keyboard._hid_helper.start_advertising()
|
||||||
return keyboard
|
return keyboard
|
||||||
|
|
||||||
|
|
||||||
def ble_disconnect(key, keyboard, *args, **kwargs):
|
|
||||||
from kmk.hid import HIDModes
|
|
||||||
|
|
||||||
if keyboard.hid_type != HIDModes.BLE:
|
|
||||||
return keyboard
|
|
||||||
|
|
||||||
keyboard._hid_helper.clear_bonds()
|
|
||||||
return keyboard
|
|
||||||
|
95
kmk/hid.py
95
kmk/hid.py
@@ -4,8 +4,7 @@ from micropython import const
|
|||||||
|
|
||||||
from storage import getmount
|
from storage import getmount
|
||||||
|
|
||||||
from kmk.keys import FIRST_KMK_INTERNAL_KEY, ConsumerKey, ModifierKey, MouseKey
|
from kmk.keys import FIRST_KMK_INTERNAL_KEY, ConsumerKey, ModifierKey
|
||||||
from kmk.utils import clamp
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from adafruit_ble import BLERadio
|
from adafruit_ble import BLERadio
|
||||||
@@ -69,14 +68,6 @@ class AbstractHID:
|
|||||||
self.report_mods = memoryview(self._evt)[1:2]
|
self.report_mods = memoryview(self._evt)[1:2]
|
||||||
self.report_non_mods = memoryview(self._evt)[3:]
|
self.report_non_mods = memoryview(self._evt)[3:]
|
||||||
|
|
||||||
self._cc_report = bytearray(HID_REPORT_SIZES[HIDReportTypes.CONSUMER] + 1)
|
|
||||||
self._cc_report[0] = HIDReportTypes.CONSUMER
|
|
||||||
self._cc_pending = False
|
|
||||||
|
|
||||||
self._pd_report = bytearray(HID_REPORT_SIZES[HIDReportTypes.MOUSE] + 1)
|
|
||||||
self._pd_report[0] = HIDReportTypes.MOUSE
|
|
||||||
self._pd_pending = False
|
|
||||||
|
|
||||||
self.post_init()
|
self.post_init()
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
@@ -85,27 +76,47 @@ class AbstractHID:
|
|||||||
def post_init(self):
|
def post_init(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def create_report(self, keys_pressed, axes):
|
def create_report(self, keys_pressed):
|
||||||
self.clear_all()
|
self.clear_all()
|
||||||
|
|
||||||
|
consumer_key = None
|
||||||
|
for key in keys_pressed:
|
||||||
|
if isinstance(key, ConsumerKey):
|
||||||
|
consumer_key = key
|
||||||
|
break
|
||||||
|
|
||||||
|
reporting_device = self.report_device[0]
|
||||||
|
needed_reporting_device = HIDReportTypes.KEYBOARD
|
||||||
|
|
||||||
|
if consumer_key:
|
||||||
|
needed_reporting_device = HIDReportTypes.CONSUMER
|
||||||
|
|
||||||
|
if reporting_device != needed_reporting_device:
|
||||||
|
# If we are about to change reporting devices, release
|
||||||
|
# all keys and close our proverbial tab on the existing
|
||||||
|
# device, or keys will get stuck (mostly when releasing
|
||||||
|
# media/consumer keys)
|
||||||
|
self.send()
|
||||||
|
|
||||||
|
self.report_device[0] = needed_reporting_device
|
||||||
|
|
||||||
|
if consumer_key:
|
||||||
|
self.add_key(consumer_key)
|
||||||
|
else:
|
||||||
for key in keys_pressed:
|
for key in keys_pressed:
|
||||||
if key.code >= FIRST_KMK_INTERNAL_KEY:
|
if key.code >= FIRST_KMK_INTERNAL_KEY:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if isinstance(key, ModifierKey):
|
if isinstance(key, ModifierKey):
|
||||||
self.add_modifier(key)
|
self.add_modifier(key)
|
||||||
elif isinstance(key, ConsumerKey):
|
|
||||||
self.add_cc(key)
|
|
||||||
elif isinstance(key, MouseKey):
|
|
||||||
self.add_pd(key)
|
|
||||||
else:
|
else:
|
||||||
self.add_key(key)
|
self.add_key(key)
|
||||||
|
|
||||||
if key.has_modifiers:
|
if key.has_modifiers:
|
||||||
for mod in key.has_modifiers:
|
for mod in key.has_modifiers:
|
||||||
self.add_modifier(mod)
|
self.add_modifier(mod)
|
||||||
|
|
||||||
for axis in axes:
|
return self
|
||||||
self.move_axis(axis)
|
|
||||||
|
|
||||||
def hid_send(self, evt):
|
def hid_send(self, evt):
|
||||||
# Don't raise a NotImplementedError so this can serve as our "dummy" HID
|
# Don't raise a NotImplementedError so this can serve as our "dummy" HID
|
||||||
@@ -120,24 +131,12 @@ class AbstractHID:
|
|||||||
self._prev_evt[:] = self._evt
|
self._prev_evt[:] = self._evt
|
||||||
self.hid_send(self._evt)
|
self.hid_send(self._evt)
|
||||||
|
|
||||||
if self._cc_pending:
|
|
||||||
self.hid_send(self._cc_report)
|
|
||||||
self._cc_pending = False
|
|
||||||
|
|
||||||
if self._pd_pending:
|
|
||||||
self.hid_send(self._pd_report)
|
|
||||||
self._pd_pending = False
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def clear_all(self):
|
def clear_all(self):
|
||||||
for idx, _ in enumerate(self.report_keys):
|
for idx, _ in enumerate(self.report_keys):
|
||||||
self.report_keys[idx] = 0x00
|
self.report_keys[idx] = 0x00
|
||||||
|
|
||||||
self.remove_cc()
|
|
||||||
self.remove_pd()
|
|
||||||
self.clear_axis()
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def clear_non_modifiers(self):
|
def clear_non_modifiers(self):
|
||||||
@@ -176,6 +175,9 @@ class AbstractHID:
|
|||||||
|
|
||||||
where_to_place = self.report_non_mods
|
where_to_place = self.report_non_mods
|
||||||
|
|
||||||
|
if self.report_device[0] == HIDReportTypes.CONSUMER:
|
||||||
|
where_to_place = self.report_keys
|
||||||
|
|
||||||
for idx, _ in enumerate(where_to_place):
|
for idx, _ in enumerate(where_to_place):
|
||||||
if where_to_place[idx] == 0x00:
|
if where_to_place[idx] == 0x00:
|
||||||
where_to_place[idx] = key.code
|
where_to_place[idx] = key.code
|
||||||
@@ -191,44 +193,15 @@ class AbstractHID:
|
|||||||
def remove_key(self, key):
|
def remove_key(self, key):
|
||||||
where_to_place = self.report_non_mods
|
where_to_place = self.report_non_mods
|
||||||
|
|
||||||
|
if self.report_device[0] == HIDReportTypes.CONSUMER:
|
||||||
|
where_to_place = self.report_keys
|
||||||
|
|
||||||
for idx, _ in enumerate(where_to_place):
|
for idx, _ in enumerate(where_to_place):
|
||||||
if where_to_place[idx] == key.code:
|
if where_to_place[idx] == key.code:
|
||||||
where_to_place[idx] = 0x00
|
where_to_place[idx] = 0x00
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def add_cc(self, cc):
|
|
||||||
# Add (or write over) consumer control report. There can only be one CC
|
|
||||||
# active at any time.
|
|
||||||
memoryview(self._cc_report)[1:3] = cc.code.to_bytes(2, 'little')
|
|
||||||
self._cc_pending = True
|
|
||||||
|
|
||||||
def remove_cc(self):
|
|
||||||
# Remove consumer control report.
|
|
||||||
report = memoryview(self._cc_report)[1:3]
|
|
||||||
if report != b'\x00\x00':
|
|
||||||
report[:] = b'\x00\x00'
|
|
||||||
self._cc_pending = True
|
|
||||||
|
|
||||||
def add_pd(self, key):
|
|
||||||
self._pd_report[1] |= key.code
|
|
||||||
self._pd_pending = True
|
|
||||||
|
|
||||||
def remove_pd(self):
|
|
||||||
if self._pd_report[1]:
|
|
||||||
self._pd_pending = True
|
|
||||||
self._pd_report[1] = 0x00
|
|
||||||
|
|
||||||
def move_axis(self, axis):
|
|
||||||
delta = clamp(axis.delta, -127, 127)
|
|
||||||
axis.delta -= delta
|
|
||||||
self._pd_report[axis.code + 2] = 0xFF & delta
|
|
||||||
self._pd_pending = True
|
|
||||||
|
|
||||||
def clear_axis(self):
|
|
||||||
for idx in range(2, len(self._pd_report)):
|
|
||||||
self._pd_report[idx] = 0x00
|
|
||||||
|
|
||||||
|
|
||||||
class USBHID(AbstractHID):
|
class USBHID(AbstractHID):
|
||||||
REPORT_BYTES = 9
|
REPORT_BYTES = 9
|
||||||
|
35
kmk/keys.py
35
kmk/keys.py
@@ -20,7 +20,6 @@ class KeyType:
|
|||||||
SIMPLE = const(0)
|
SIMPLE = const(0)
|
||||||
MODIFIER = const(1)
|
MODIFIER = const(1)
|
||||||
CONSUMER = const(2)
|
CONSUMER = const(2)
|
||||||
MOUSE = const(3)
|
|
||||||
|
|
||||||
|
|
||||||
FIRST_KMK_INTERNAL_KEY = const(1000)
|
FIRST_KMK_INTERNAL_KEY = const(1000)
|
||||||
@@ -34,29 +33,6 @@ ALL_NUMBER_ALIASES = tuple(f'N{x}' for x in ALL_NUMBERS)
|
|||||||
debug = Debug(__name__)
|
debug = Debug(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Axis:
|
|
||||||
def __init__(self, code: int) -> None:
|
|
||||||
self.code = code
|
|
||||||
self.delta = 0
|
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
|
||||||
return f'Axis(code={self.code}, delta={self.delta})'
|
|
||||||
|
|
||||||
def move(self, keyboard: Keyboard, delta: int):
|
|
||||||
self.delta += delta
|
|
||||||
if self.delta:
|
|
||||||
keyboard.axes.add(self)
|
|
||||||
keyboard.hid_pending = True
|
|
||||||
else:
|
|
||||||
keyboard.axes.discard(self)
|
|
||||||
|
|
||||||
|
|
||||||
class AX:
|
|
||||||
W = Axis(2)
|
|
||||||
X = Axis(0)
|
|
||||||
Y = Axis(1)
|
|
||||||
|
|
||||||
|
|
||||||
def maybe_make_key(
|
def maybe_make_key(
|
||||||
code: Optional[int],
|
code: Optional[int],
|
||||||
names: Tuple[str, ...],
|
names: Tuple[str, ...],
|
||||||
@@ -364,7 +340,6 @@ def maybe_make_unicode_key(candidate: str) -> Optional[Key]:
|
|||||||
def maybe_make_firmware_key(candidate: str) -> Optional[Key]:
|
def maybe_make_firmware_key(candidate: str) -> Optional[Key]:
|
||||||
keys = (
|
keys = (
|
||||||
((('BLE_REFRESH',), handlers.ble_refresh)),
|
((('BLE_REFRESH',), handlers.ble_refresh)),
|
||||||
((('BLE_DISCONNECT',), handlers.ble_disconnect)),
|
|
||||||
((('BOOTLOADER',), handlers.bootloader)),
|
((('BOOTLOADER',), handlers.bootloader)),
|
||||||
((('DEBUG', 'DBG'), handlers.debug_pressed)),
|
((('DEBUG', 'DBG'), handlers.debug_pressed)),
|
||||||
((('HID_SWITCH', 'HID'), handlers.hid_switch)),
|
((('HID_SWITCH', 'HID'), handlers.hid_switch)),
|
||||||
@@ -713,10 +688,6 @@ class ConsumerKey(Key):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class MouseKey(Key):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def make_key(
|
def make_key(
|
||||||
code: Optional[int] = None,
|
code: Optional[int] = None,
|
||||||
names: Tuple[str, ...] = tuple(), # NOQA
|
names: Tuple[str, ...] = tuple(), # NOQA
|
||||||
@@ -747,8 +718,6 @@ def make_key(
|
|||||||
constructor = ModifierKey
|
constructor = ModifierKey
|
||||||
elif type == KeyType.CONSUMER:
|
elif type == KeyType.CONSUMER:
|
||||||
constructor = ConsumerKey
|
constructor = ConsumerKey
|
||||||
elif type == KeyType.MOUSE:
|
|
||||||
constructor = MouseKey
|
|
||||||
else:
|
else:
|
||||||
raise ValueError('Unrecognized key type')
|
raise ValueError('Unrecognized key type')
|
||||||
|
|
||||||
@@ -781,10 +750,6 @@ def make_consumer_key(*args, **kwargs) -> Key:
|
|||||||
return make_key(*args, **kwargs, type=KeyType.CONSUMER)
|
return make_key(*args, **kwargs, type=KeyType.CONSUMER)
|
||||||
|
|
||||||
|
|
||||||
def make_mouse_key(*args, **kwargs) -> Key:
|
|
||||||
return make_key(*args, **kwargs, type=KeyType.MOUSE)
|
|
||||||
|
|
||||||
|
|
||||||
# Argumented keys are implicitly internal, so auto-gen of code
|
# Argumented keys are implicitly internal, so auto-gen of code
|
||||||
# is almost certainly the best plan here
|
# is almost certainly the best plan here
|
||||||
def make_argumented_key(
|
def make_argumented_key(
|
||||||
|
@@ -49,7 +49,6 @@ class KMKKeyboard:
|
|||||||
#####
|
#####
|
||||||
# Internal State
|
# Internal State
|
||||||
keys_pressed = set()
|
keys_pressed = set()
|
||||||
axes = set()
|
|
||||||
_coordkeys_pressed = {}
|
_coordkeys_pressed = {}
|
||||||
hid_type = HIDModes.USB
|
hid_type = HIDModes.USB
|
||||||
secondary_hid_type = None
|
secondary_hid_type = None
|
||||||
@@ -89,7 +88,6 @@ class KMKKeyboard:
|
|||||||
f' unicode_mode={self.unicode_mode}, ',
|
f' unicode_mode={self.unicode_mode}, ',
|
||||||
f'_hid_helper={self._hid_helper},\n',
|
f'_hid_helper={self._hid_helper},\n',
|
||||||
f' keys_pressed={self.keys_pressed},\n',
|
f' keys_pressed={self.keys_pressed},\n',
|
||||||
f' axes={self.axes},\n',
|
|
||||||
f' _coordkeys_pressed={self._coordkeys_pressed},\n',
|
f' _coordkeys_pressed={self._coordkeys_pressed},\n',
|
||||||
f' hid_pending={self.hid_pending}, ',
|
f' hid_pending={self.hid_pending}, ',
|
||||||
f'active_layers={self.active_layers}, ',
|
f'active_layers={self.active_layers}, ',
|
||||||
@@ -104,24 +102,15 @@ class KMKKeyboard:
|
|||||||
debug(f'keys_pressed={self.keys_pressed}')
|
debug(f'keys_pressed={self.keys_pressed}')
|
||||||
|
|
||||||
def _send_hid(self) -> None:
|
def _send_hid(self) -> None:
|
||||||
if not self._hid_send_enabled:
|
if self._hid_send_enabled:
|
||||||
return
|
hid_report = self._hid_helper.create_report(self.keys_pressed)
|
||||||
|
|
||||||
if self.axes and debug.enabled:
|
|
||||||
debug(f'axes={self.axes}')
|
|
||||||
|
|
||||||
self._hid_helper.create_report(self.keys_pressed, self.axes)
|
|
||||||
try:
|
try:
|
||||||
self._hid_helper.send()
|
hid_report.send()
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
if debug.enabled:
|
if debug.enabled:
|
||||||
debug(f'HidNotFound(HIDReportType={e})')
|
debug(f'HidNotFound(HIDReportType={e})')
|
||||||
|
|
||||||
self.hid_pending = False
|
self.hid_pending = False
|
||||||
|
|
||||||
for axis in self.axes:
|
|
||||||
axis.move(self, 0)
|
|
||||||
|
|
||||||
def _handle_matrix_report(self, kevent: KeyEvent) -> None:
|
def _handle_matrix_report(self, kevent: KeyEvent) -> None:
|
||||||
if kevent is not None:
|
if kevent is not None:
|
||||||
self._on_matrix_changed(kevent)
|
self._on_matrix_changed(kevent)
|
||||||
|
@@ -4,9 +4,9 @@ import microcontroller
|
|||||||
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from kmk.keys import AX
|
|
||||||
from kmk.modules import Module
|
from kmk.modules import Module
|
||||||
from kmk.modules.adns9800_firmware import firmware
|
from kmk.modules.adns9800_firmware import firmware
|
||||||
|
from kmk.modules.mouse_keys import PointingDevice
|
||||||
|
|
||||||
|
|
||||||
class REG:
|
class REG:
|
||||||
@@ -70,6 +70,7 @@ class ADNS9800(Module):
|
|||||||
DIR_READ = 0x7F
|
DIR_READ = 0x7F
|
||||||
|
|
||||||
def __init__(self, cs, sclk, miso, mosi, invert_x=False, invert_y=False):
|
def __init__(self, cs, sclk, miso, mosi, invert_x=False, invert_y=False):
|
||||||
|
self.pointing_device = PointingDevice()
|
||||||
self.cs = digitalio.DigitalInOut(cs)
|
self.cs = digitalio.DigitalInOut(cs)
|
||||||
self.cs.direction = digitalio.Direction.OUTPUT
|
self.cs.direction = digitalio.Direction.OUTPUT
|
||||||
self.spi = busio.SPI(clock=sclk, MOSI=mosi, MISO=miso)
|
self.spi = busio.SPI(clock=sclk, MOSI=mosi, MISO=miso)
|
||||||
@@ -202,14 +203,27 @@ class ADNS9800(Module):
|
|||||||
if self.invert_y:
|
if self.invert_y:
|
||||||
delta_y *= -1
|
delta_y *= -1
|
||||||
|
|
||||||
if delta_x:
|
if delta_x < 0:
|
||||||
AX.X.move(delta_x)
|
self.pointing_device.report_x[0] = (delta_x & 0xFF) | 0x80
|
||||||
|
else:
|
||||||
|
self.pointing_device.report_x[0] = delta_x & 0xFF
|
||||||
|
|
||||||
if delta_y:
|
if delta_y < 0:
|
||||||
AX.Y.move(delta_y)
|
self.pointing_device.report_y[0] = (delta_y & 0xFF) | 0x80
|
||||||
|
else:
|
||||||
|
self.pointing_device.report_y[0] = delta_y & 0xFF
|
||||||
|
|
||||||
if keyboard.debug_enabled:
|
if keyboard.debug_enabled:
|
||||||
print('Delta: ', delta_x, ' ', delta_y)
|
print('Delta: ', delta_x, ' ', delta_y)
|
||||||
|
self.pointing_device.hid_pending = True
|
||||||
|
|
||||||
|
if self.pointing_device.hid_pending:
|
||||||
|
keyboard._hid_helper.hid_send(self.pointing_device._evt)
|
||||||
|
self.pointing_device.hid_pending = False
|
||||||
|
self.pointing_device.report_x[0] = 0
|
||||||
|
self.pointing_device.report_y[0] = 0
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
def after_matrix_scan(self, keyboard):
|
def after_matrix_scan(self, keyboard):
|
||||||
return
|
return
|
||||||
|
@@ -4,8 +4,8 @@ Extension handles usage of AS5013 by AMS
|
|||||||
|
|
||||||
from supervisor import ticks_ms
|
from supervisor import ticks_ms
|
||||||
|
|
||||||
from kmk.keys import AX
|
|
||||||
from kmk.modules import Module
|
from kmk.modules import Module
|
||||||
|
from kmk.modules.mouse_keys import PointingDevice
|
||||||
|
|
||||||
I2C_ADDRESS = 0x40
|
I2C_ADDRESS = 0x40
|
||||||
I2X_ALT_ADDRESS = 0x41
|
I2X_ALT_ADDRESS = 0x41
|
||||||
@@ -44,6 +44,7 @@ class Easypoint(Module):
|
|||||||
self._i2c_bus = i2c
|
self._i2c_bus = i2c
|
||||||
|
|
||||||
# HID parameters
|
# HID parameters
|
||||||
|
self.pointing_device = PointingDevice()
|
||||||
self.polling_interval = 20
|
self.polling_interval = 20
|
||||||
self.last_tick = ticks_ms()
|
self.last_tick = ticks_ms()
|
||||||
|
|
||||||
@@ -81,8 +82,12 @@ class Easypoint(Module):
|
|||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
# Set the X/Y from easypoint
|
# Set the X/Y from easypoint
|
||||||
AX.X.move(keyboard, x)
|
self.pointing_device.report_x[0] = x
|
||||||
AX.Y.move(keyboard, y)
|
self.pointing_device.report_y[0] = y
|
||||||
|
|
||||||
|
self.pointing_device.hid_pending = x != 0 or y != 0
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
def after_matrix_scan(self, keyboard):
|
def after_matrix_scan(self, keyboard):
|
||||||
return
|
return
|
||||||
@@ -91,6 +96,9 @@ class Easypoint(Module):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def after_hid_send(self, keyboard):
|
def after_hid_send(self, keyboard):
|
||||||
|
if self.pointing_device.hid_pending:
|
||||||
|
keyboard._hid_helper.hid_send(self.pointing_device._evt)
|
||||||
|
self._clear_pending_hid()
|
||||||
return
|
return
|
||||||
|
|
||||||
def on_powersave_enable(self, keyboard):
|
def on_powersave_enable(self, keyboard):
|
||||||
@@ -99,6 +107,13 @@ class Easypoint(Module):
|
|||||||
def on_powersave_disable(self, keyboard):
|
def on_powersave_disable(self, keyboard):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def _clear_pending_hid(self):
|
||||||
|
self.pointing_device.hid_pending = False
|
||||||
|
self.pointing_device.report_x[0] = 0
|
||||||
|
self.pointing_device.report_y[0] = 0
|
||||||
|
self.pointing_device.report_w[0] = 0
|
||||||
|
self.pointing_device.button_status[0] = 0
|
||||||
|
|
||||||
def _read_raw_state(self):
|
def _read_raw_state(self):
|
||||||
'''Read data from AS5013'''
|
'''Read data from AS5013'''
|
||||||
x, y = self._i2c_rdwr([X], length=2)
|
x, y = self._i2c_rdwr([X], length=2)
|
||||||
|
@@ -114,15 +114,17 @@ class Layers(HoldTap):
|
|||||||
'''
|
'''
|
||||||
As MO(layer) but with mod active
|
As MO(layer) but with mod active
|
||||||
'''
|
'''
|
||||||
|
keyboard.hid_pending = True
|
||||||
# Sets the timer start and acts like MO otherwise
|
# Sets the timer start and acts like MO otherwise
|
||||||
keyboard.add_key(key.meta.kc)
|
keyboard.keys_pressed.add(key.meta.kc)
|
||||||
self._mo_pressed(key, keyboard, *args, **kwargs)
|
self._mo_pressed(key, keyboard, *args, **kwargs)
|
||||||
|
|
||||||
def _lm_released(self, key, keyboard, *args, **kwargs):
|
def _lm_released(self, key, keyboard, *args, **kwargs):
|
||||||
'''
|
'''
|
||||||
As MO(layer) but with mod active
|
As MO(layer) but with mod active
|
||||||
'''
|
'''
|
||||||
keyboard.remove_key(key.meta.kc)
|
keyboard.hid_pending = True
|
||||||
|
keyboard.keys_pressed.discard(key.meta.kc)
|
||||||
self._mo_released(key, keyboard, *args, **kwargs)
|
self._mo_released(key, keyboard, *args, **kwargs)
|
||||||
|
|
||||||
def _tg_pressed(self, key, keyboard, *args, **kwargs):
|
def _tg_pressed(self, key, keyboard, *args, **kwargs):
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
|
from supervisor import ticks_ms
|
||||||
|
|
||||||
from kmk.hid import HID_REPORT_SIZES, HIDReportTypes
|
from kmk.hid import HID_REPORT_SIZES, HIDReportTypes
|
||||||
from kmk.keys import AX, make_key, make_mouse_key
|
from kmk.keys import make_key
|
||||||
from kmk.kmktime import PeriodicTimer
|
|
||||||
from kmk.modules import Module
|
from kmk.modules import Module
|
||||||
|
|
||||||
|
|
||||||
@@ -23,28 +24,31 @@ class PointingDevice:
|
|||||||
|
|
||||||
class MouseKeys(Module):
|
class MouseKeys(Module):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
self.pointing_device = PointingDevice()
|
||||||
self._nav_key_activated = 0
|
self._nav_key_activated = 0
|
||||||
self._up_activated = False
|
self._up_activated = False
|
||||||
self._down_activated = False
|
self._down_activated = False
|
||||||
self._left_activated = False
|
self._left_activated = False
|
||||||
self._right_activated = False
|
self._right_activated = False
|
||||||
self._mw_up_activated = False
|
|
||||||
self._mw_down_activated = False
|
|
||||||
self.max_speed = 10
|
self.max_speed = 10
|
||||||
self.acc_interval = 10 # Delta ms to apply acceleration
|
self.ac_interval = 100 # Delta ms to apply acceleration
|
||||||
|
self._next_interval = 0 # Time for next tick interval
|
||||||
self.move_step = 1
|
self.move_step = 1
|
||||||
|
|
||||||
make_mouse_key(
|
make_key(
|
||||||
names=('MB_LMB',),
|
names=('MB_LMB',),
|
||||||
code=1,
|
on_press=self._mb_lmb_press,
|
||||||
|
on_release=self._mb_lmb_release,
|
||||||
)
|
)
|
||||||
make_mouse_key(
|
make_key(
|
||||||
names=('MB_MMB',),
|
names=('MB_MMB',),
|
||||||
code=4,
|
on_press=self._mb_mmb_press,
|
||||||
|
on_release=self._mb_mmb_release,
|
||||||
)
|
)
|
||||||
make_mouse_key(
|
make_key(
|
||||||
names=('MB_RMB',),
|
names=('MB_RMB',),
|
||||||
code=2,
|
on_press=self._mb_rmb_press,
|
||||||
|
on_release=self._mb_rmb_release,
|
||||||
)
|
)
|
||||||
make_key(
|
make_key(
|
||||||
names=('MW_UP',),
|
names=('MW_UP',),
|
||||||
@@ -90,33 +94,38 @@ class MouseKeys(Module):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def during_bootup(self, keyboard):
|
def during_bootup(self, keyboard):
|
||||||
self._timer = PeriodicTimer(self.acc_interval)
|
return
|
||||||
|
|
||||||
|
def matrix_detected_press(self, keyboard):
|
||||||
|
return keyboard.matrix_update is None
|
||||||
|
|
||||||
def before_matrix_scan(self, keyboard):
|
def before_matrix_scan(self, keyboard):
|
||||||
return
|
return
|
||||||
|
|
||||||
def after_matrix_scan(self, keyboard):
|
def after_matrix_scan(self, keyboard):
|
||||||
if not self._timer.tick():
|
|
||||||
return
|
|
||||||
|
|
||||||
if self._nav_key_activated:
|
if self._nav_key_activated:
|
||||||
|
if self._next_interval <= ticks_ms():
|
||||||
|
# print("hello: ")
|
||||||
|
# print(ticks_ms())
|
||||||
|
self._next_interval = ticks_ms() + self.ac_interval
|
||||||
|
# print(self._next_interval)
|
||||||
if self.move_step < self.max_speed:
|
if self.move_step < self.max_speed:
|
||||||
self.move_step = self.move_step + 1
|
self.move_step = self.move_step + 1
|
||||||
if self._right_activated:
|
if self._right_activated:
|
||||||
AX.X.move(keyboard, self.move_step)
|
self.pointing_device.report_x[0] = self.move_step
|
||||||
if self._left_activated:
|
if self._left_activated:
|
||||||
AX.X.move(keyboard, -self.move_step)
|
self.pointing_device.report_x[0] = 0xFF & (0 - self.move_step)
|
||||||
if self._up_activated:
|
if self._up_activated:
|
||||||
AX.Y.move(keyboard, -self.move_step)
|
self.pointing_device.report_y[0] = 0xFF & (0 - self.move_step)
|
||||||
if self._down_activated:
|
if self._down_activated:
|
||||||
AX.Y.move(keyboard, self.move_step)
|
self.pointing_device.report_y[0] = self.move_step
|
||||||
|
self.pointing_device.hid_pending = True
|
||||||
if self._mw_up_activated:
|
return
|
||||||
AX.W.move(keyboard, 1)
|
|
||||||
if self._mw_down_activated:
|
|
||||||
AX.W.move(keyboard, -1)
|
|
||||||
|
|
||||||
def before_hid_send(self, keyboard):
|
def before_hid_send(self, keyboard):
|
||||||
|
if self.pointing_device.hid_pending and keyboard._hid_send_enabled:
|
||||||
|
keyboard._hid_helper.hid_send(self.pointing_device._evt)
|
||||||
|
self.pointing_device.hid_pending = False
|
||||||
return
|
return
|
||||||
|
|
||||||
def after_hid_send(self, keyboard):
|
def after_hid_send(self, keyboard):
|
||||||
@@ -128,21 +137,50 @@ class MouseKeys(Module):
|
|||||||
def on_powersave_disable(self, keyboard):
|
def on_powersave_disable(self, keyboard):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def _mb_lmb_press(self, key, keyboard, *args, **kwargs):
|
||||||
|
self.pointing_device.button_status[0] |= self.pointing_device.MB_LMB
|
||||||
|
self.pointing_device.hid_pending = True
|
||||||
|
|
||||||
|
def _mb_lmb_release(self, key, keyboard, *args, **kwargs):
|
||||||
|
self.pointing_device.button_status[0] &= ~self.pointing_device.MB_LMB
|
||||||
|
self.pointing_device.hid_pending = True
|
||||||
|
|
||||||
|
def _mb_mmb_press(self, key, keyboard, *args, **kwargs):
|
||||||
|
self.pointing_device.button_status[0] |= self.pointing_device.MB_MMB
|
||||||
|
self.pointing_device.hid_pending = True
|
||||||
|
|
||||||
|
def _mb_mmb_release(self, key, keyboard, *args, **kwargs):
|
||||||
|
self.pointing_device.button_status[0] &= ~self.pointing_device.MB_MMB
|
||||||
|
self.pointing_device.hid_pending = True
|
||||||
|
|
||||||
|
def _mb_rmb_press(self, key, keyboard, *args, **kwargs):
|
||||||
|
self.pointing_device.button_status[0] |= self.pointing_device.MB_RMB
|
||||||
|
self.pointing_device.hid_pending = True
|
||||||
|
|
||||||
|
def _mb_rmb_release(self, key, keyboard, *args, **kwargs):
|
||||||
|
self.pointing_device.button_status[0] &= ~self.pointing_device.MB_RMB
|
||||||
|
self.pointing_device.hid_pending = True
|
||||||
|
|
||||||
def _mw_up_press(self, key, keyboard, *args, **kwargs):
|
def _mw_up_press(self, key, keyboard, *args, **kwargs):
|
||||||
self._mw_up_activated = True
|
self.pointing_device.report_w[0] = self.move_step
|
||||||
|
self.pointing_device.hid_pending = True
|
||||||
|
|
||||||
def _mw_up_release(self, key, keyboard, *args, **kwargs):
|
def _mw_up_release(self, key, keyboard, *args, **kwargs):
|
||||||
self._mw_up_activated = False
|
self.pointing_device.report_w[0] = 0
|
||||||
|
self.pointing_device.hid_pending = True
|
||||||
|
|
||||||
def _mw_down_press(self, key, keyboard, *args, **kwargs):
|
def _mw_down_press(self, key, keyboard, *args, **kwargs):
|
||||||
self._mw_down_activated = True
|
self.pointing_device.report_w[0] = 0xFF
|
||||||
|
self.pointing_device.hid_pending = True
|
||||||
|
|
||||||
def _mw_down_release(self, key, keyboard, *args, **kwargs):
|
def _mw_down_release(self, key, keyboard, *args, **kwargs):
|
||||||
self._mw_down_activated = False
|
self.pointing_device.report_w[0] = 0
|
||||||
|
self.pointing_device.hid_pending = True
|
||||||
|
|
||||||
# Mouse movement
|
# Mouse movement
|
||||||
def _reset_next_interval(self):
|
def _reset_next_interval(self):
|
||||||
if self._nav_key_activated == 1:
|
if self._nav_key_activated == 1:
|
||||||
|
self._next_interval = ticks_ms() + self.ac_interval
|
||||||
self.move_step = 1
|
self.move_step = 1
|
||||||
|
|
||||||
def _check_last(self):
|
def _check_last(self):
|
||||||
@@ -153,38 +191,56 @@ class MouseKeys(Module):
|
|||||||
self._nav_key_activated += 1
|
self._nav_key_activated += 1
|
||||||
self._reset_next_interval()
|
self._reset_next_interval()
|
||||||
self._up_activated = True
|
self._up_activated = True
|
||||||
|
self.pointing_device.report_y[0] = 0xFF & (0 - self.move_step)
|
||||||
|
self.pointing_device.hid_pending = True
|
||||||
|
|
||||||
def _ms_up_release(self, key, keyboard, *args, **kwargs):
|
def _ms_up_release(self, key, keyboard, *args, **kwargs):
|
||||||
self._up_activated = False
|
self._up_activated = False
|
||||||
self._nav_key_activated -= 1
|
self._nav_key_activated -= 1
|
||||||
self._check_last()
|
self._check_last()
|
||||||
|
self.pointing_device.report_y[0] = 0
|
||||||
|
self.pointing_device.hid_pending = False
|
||||||
|
|
||||||
def _ms_down_press(self, key, keyboard, *args, **kwargs):
|
def _ms_down_press(self, key, keyboard, *args, **kwargs):
|
||||||
self._nav_key_activated += 1
|
self._nav_key_activated += 1
|
||||||
self._reset_next_interval()
|
self._reset_next_interval()
|
||||||
self._down_activated = True
|
self._down_activated = True
|
||||||
|
# if not self.x_activated and not self.y_activated:
|
||||||
|
# self.next_interval = ticks_ms() + self.ac_intervalle
|
||||||
|
self.pointing_device.report_y[0] = self.move_step
|
||||||
|
self.pointing_device.hid_pending = True
|
||||||
|
|
||||||
def _ms_down_release(self, key, keyboard, *args, **kwargs):
|
def _ms_down_release(self, key, keyboard, *args, **kwargs):
|
||||||
self._down_activated = False
|
self._down_activated = False
|
||||||
self._nav_key_activated -= 1
|
self._nav_key_activated -= 1
|
||||||
self._check_last()
|
self._check_last()
|
||||||
|
self.pointing_device.report_y[0] = 0
|
||||||
|
self.pointing_device.hid_pending = False
|
||||||
|
|
||||||
def _ms_left_press(self, key, keyboard, *args, **kwargs):
|
def _ms_left_press(self, key, keyboard, *args, **kwargs):
|
||||||
self._nav_key_activated += 1
|
self._nav_key_activated += 1
|
||||||
self._reset_next_interval()
|
self._reset_next_interval()
|
||||||
self._left_activated = True
|
self._left_activated = True
|
||||||
|
self.pointing_device.report_x[0] = 0xFF & (0 - self.move_step)
|
||||||
|
self.pointing_device.hid_pending = True
|
||||||
|
|
||||||
def _ms_left_release(self, key, keyboard, *args, **kwargs):
|
def _ms_left_release(self, key, keyboard, *args, **kwargs):
|
||||||
self._nav_key_activated -= 1
|
self._nav_key_activated -= 1
|
||||||
self._left_activated = False
|
self._left_activated = False
|
||||||
self._check_last()
|
self._check_last()
|
||||||
|
self.pointing_device.report_x[0] = 0
|
||||||
|
self.pointing_device.hid_pending = False
|
||||||
|
|
||||||
def _ms_right_press(self, key, keyboard, *args, **kwargs):
|
def _ms_right_press(self, key, keyboard, *args, **kwargs):
|
||||||
self._nav_key_activated += 1
|
self._nav_key_activated += 1
|
||||||
self._reset_next_interval()
|
self._reset_next_interval()
|
||||||
self._right_activated = True
|
self._right_activated = True
|
||||||
|
self.pointing_device.report_x[0] = self.move_step
|
||||||
|
self.pointing_device.hid_pending = True
|
||||||
|
|
||||||
def _ms_right_release(self, key, keyboard, *args, **kwargs):
|
def _ms_right_release(self, key, keyboard, *args, **kwargs):
|
||||||
self._nav_key_activated -= 1
|
self._nav_key_activated -= 1
|
||||||
self._right_activated = False
|
self._right_activated = False
|
||||||
self._check_last()
|
self._check_last()
|
||||||
|
self.pointing_device.report_x[0] = 0
|
||||||
|
self.pointing_device.hid_pending = False
|
||||||
|
@@ -7,9 +7,10 @@ from micropython import const
|
|||||||
import math
|
import math
|
||||||
import struct
|
import struct
|
||||||
|
|
||||||
from kmk.keys import AX, KC, make_argumented_key, make_key
|
from kmk.keys import make_argumented_key, make_key
|
||||||
from kmk.kmktime import PeriodicTimer
|
from kmk.kmktime import PeriodicTimer
|
||||||
from kmk.modules import Module
|
from kmk.modules import Module
|
||||||
|
from kmk.modules.mouse_keys import PointingDevice
|
||||||
|
|
||||||
I2C_ADDRESS = 0x0A
|
I2C_ADDRESS = 0x0A
|
||||||
I2C_ADDRESS_ALTERNATIVE = 0x0B
|
I2C_ADDRESS_ALTERNATIVE = 0x0B
|
||||||
@@ -77,16 +78,29 @@ class TrackballHandler:
|
|||||||
|
|
||||||
class PointingHandler(TrackballHandler):
|
class PointingHandler(TrackballHandler):
|
||||||
def handle(self, keyboard, trackball, x, y, switch, state):
|
def handle(self, keyboard, trackball, x, y, switch, state):
|
||||||
if x:
|
if x > 0:
|
||||||
AX.X.move(keyboard, x)
|
trackball.pointing_device.report_x[0] = x
|
||||||
if y:
|
elif x < 0:
|
||||||
AX.Y.move(keyboard, y)
|
trackball.pointing_device.report_x[0] = 0xFF & x
|
||||||
|
if y > 0:
|
||||||
|
trackball.pointing_device.report_y[0] = y
|
||||||
|
elif y < 0:
|
||||||
|
trackball.pointing_device.report_y[0] = 0xFF & y
|
||||||
|
|
||||||
|
if x != 0 or y != 0:
|
||||||
|
trackball.pointing_device.hid_pending = True
|
||||||
|
|
||||||
if switch == 1: # Button pressed
|
if switch == 1: # Button pressed
|
||||||
keyboard.pre_process_key(KC.MB_LMB, is_pressed=True)
|
trackball.pointing_device.button_status[
|
||||||
|
0
|
||||||
|
] |= trackball.pointing_device.MB_LMB
|
||||||
|
trackball.pointing_device.hid_pending = True
|
||||||
|
|
||||||
if not state and trackball.previous_state is True: # Button released
|
if not state and trackball.previous_state is True: # Button released
|
||||||
keyboard.pre_process_key(KC.MB_LMB, is_pressed=False)
|
trackball.pointing_device.button_status[
|
||||||
|
0
|
||||||
|
] &= ~trackball.pointing_device.MB_LMB
|
||||||
|
trackball.pointing_device.hid_pending = True
|
||||||
|
|
||||||
trackball.previous_state = state
|
trackball.previous_state = state
|
||||||
|
|
||||||
@@ -100,13 +114,17 @@ class ScrollHandler(TrackballHandler):
|
|||||||
y = -y
|
y = -y
|
||||||
|
|
||||||
if y != 0:
|
if y != 0:
|
||||||
AX.W.move(keyboard, y)
|
pointing_device = trackball.pointing_device
|
||||||
|
pointing_device.report_w[0] = 0xFF & y
|
||||||
|
pointing_device.hid_pending = True
|
||||||
|
|
||||||
if switch == 1: # Button pressed
|
if switch == 1: # Button pressed
|
||||||
keyboard.pre_process_key(KC.MB_LMB, is_pressed=True)
|
pointing_device.button_status[0] |= pointing_device.MB_LMB
|
||||||
|
pointing_device.hid_pending = True
|
||||||
|
|
||||||
if not state and trackball.previous_state is True: # Button released
|
if not state and trackball.previous_state is True: # Button released
|
||||||
keyboard.pre_process_key(KC.MB_LMB, is_pressed=False)
|
pointing_device.button_status[0] &= ~pointing_device.MB_LMB
|
||||||
|
pointing_device.hid_pending = True
|
||||||
|
|
||||||
trackball.previous_state = state
|
trackball.previous_state = state
|
||||||
|
|
||||||
@@ -167,6 +185,7 @@ class Trackball(Module):
|
|||||||
self._i2c_address = address
|
self._i2c_address = address
|
||||||
self._i2c_bus = i2c
|
self._i2c_bus = i2c
|
||||||
|
|
||||||
|
self.pointing_device = PointingDevice()
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
self.previous_state = False # click state
|
self.previous_state = False # click state
|
||||||
self.handlers = handlers
|
self.handlers = handlers
|
||||||
@@ -215,6 +234,9 @@ class Trackball(Module):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def after_hid_send(self, keyboard):
|
def after_hid_send(self, keyboard):
|
||||||
|
if self.pointing_device.hid_pending:
|
||||||
|
keyboard._hid_helper.hid_send(self.pointing_device._evt)
|
||||||
|
self._clear_pending_hid()
|
||||||
return
|
return
|
||||||
|
|
||||||
def on_powersave_enable(self, keyboard):
|
def on_powersave_enable(self, keyboard):
|
||||||
@@ -258,6 +280,13 @@ class Trackball(Module):
|
|||||||
next_index = 0
|
next_index = 0
|
||||||
self.activate_handler(next_index)
|
self.activate_handler(next_index)
|
||||||
|
|
||||||
|
def _clear_pending_hid(self):
|
||||||
|
self.pointing_device.hid_pending = False
|
||||||
|
self.pointing_device.report_x[0] = 0
|
||||||
|
self.pointing_device.report_y[0] = 0
|
||||||
|
self.pointing_device.report_w[0] = 0
|
||||||
|
self.pointing_device.button_status[0] = 0
|
||||||
|
|
||||||
def _read_raw_state(self):
|
def _read_raw_state(self):
|
||||||
'''Read up, down, left, right and switch data from trackball.'''
|
'''Read up, down, left, right and switch data from trackball.'''
|
||||||
left, right, up, down, switch = self._i2c_rdwr([REG_LEFT], 5)
|
left, right, up, down, switch = self._i2c_rdwr([REG_LEFT], 5)
|
||||||
|
@@ -1,39 +0,0 @@
|
|||||||
FROM python:3.9-slim-buster
|
|
||||||
|
|
||||||
ARG KMKPY_REF
|
|
||||||
ARG KMKPY_URL
|
|
||||||
|
|
||||||
ENV KMKPY_REF ${KMKPY_REF}
|
|
||||||
ENV KMKPY_URL ${KMKPY_URL}
|
|
||||||
|
|
||||||
RUN mkdir -p /app /dist
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y build-essential curl gettext git git-lfs rsync wget zip lbzip2
|
|
||||||
RUN pip install pipenv
|
|
||||||
|
|
||||||
# Pull CircuitPython-designated ARM GCC to avoid mismatches/weird
|
|
||||||
# inconsistencies with upstream
|
|
||||||
RUN curl -L -o /tmp/gcc-arm.tar.bz2 https://adafruit-circuit-python.s3.amazonaws.com/gcc-arm-none-eabi-9-2019-q4-major-x86_64-linux.tar.bz2 && \
|
|
||||||
tar -C /usr --strip-components=1 -xaf /tmp/gcc-arm.tar.bz2 && \
|
|
||||||
rm -rf /tmp/gcc-arm.tar.bz2
|
|
||||||
|
|
||||||
# Get a local copy of KMKPython and its dependencies. We don't provide MPY
|
|
||||||
# builds for kmkpython anymore, so we can get away with being opinionated
|
|
||||||
# here.
|
|
||||||
RUN git init /opt/kmkpython && \
|
|
||||||
git -C /opt/kmkpython remote add origin ${KMKPY_URL} && \
|
|
||||||
git -C /opt/kmkpython fetch --depth 1 origin ${KMKPY_REF} && \
|
|
||||||
git -C /opt/kmkpython checkout FETCH_HEAD && \
|
|
||||||
git -C /opt/kmkpython submodule update --init --recursive
|
|
||||||
|
|
||||||
# Build the MPY compiler
|
|
||||||
RUN make -C /opt/kmkpython/mpy-cross
|
|
||||||
|
|
||||||
ENV PATH=/opt/kmkpython/mpy-cross:${PATH}
|
|
||||||
|
|
||||||
RUN mkdir -p /opt/kmkpython/frozen/kmk/kmk
|
|
||||||
COPY ./build_kmkpython_release.sh /app/
|
|
||||||
COPY ./kmk /opt/kmkpython/frozen/kmk/kmk
|
|
||||||
|
|
||||||
CMD /app/build_kmkpython_release.sh
|
|
BIN
mpy-cross-7
BIN
mpy-cross-7
Binary file not shown.
BIN
mpy-cross-8
BIN
mpy-cross-8
Binary file not shown.
Reference in New Issue
Block a user