attempt to merge sofubi/static-type-checking, albeit incompletely
This commit is contained in:
@@ -11,3 +11,17 @@ class UnicodeMode:
|
||||
LINUX = IBUS = const(1)
|
||||
MACOS = OSX = RALT = const(2)
|
||||
WINC = const(3)
|
||||
|
||||
|
||||
TYPING_PLATFORMS = [
|
||||
'linux',
|
||||
'linux2',
|
||||
'win32',
|
||||
'cygwin',
|
||||
'msys',
|
||||
'darwin',
|
||||
'freebsd7',
|
||||
'freebsd8',
|
||||
'freebsdN',
|
||||
'openbsd6',
|
||||
]
|
||||
|
@@ -1,16 +1,21 @@
|
||||
from kmk.kmk_keyboard import KMKKeyboard
|
||||
|
||||
|
||||
class InvalidExtensionEnvironment(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class Extension:
|
||||
_enabled = True
|
||||
_enabled = True # type: bool
|
||||
|
||||
def enable(self, keyboard):
|
||||
# type: (KMKKeyboard) -> None
|
||||
self._enabled = True
|
||||
|
||||
self.on_runtime_enable(keyboard)
|
||||
|
||||
def disable(self, keyboard):
|
||||
# type (KMKKeyboard) -> None
|
||||
self._enabled = False
|
||||
|
||||
self.on_runtime_disable(keyboard)
|
||||
@@ -18,34 +23,43 @@ class Extension:
|
||||
# The below methods should be implemented by subclasses
|
||||
|
||||
def on_runtime_enable(self, keyboard):
|
||||
# type: (KMKKeyboard) -> None
|
||||
raise NotImplementedError
|
||||
|
||||
def on_runtime_disable(self, keyboard):
|
||||
# type: (KMKKeyboard) -> None
|
||||
raise NotImplementedError
|
||||
|
||||
def during_bootup(self, keyboard):
|
||||
# type: (KMKKeyboard) -> None
|
||||
raise NotImplementedError
|
||||
|
||||
def before_matrix_scan(self, keyboard):
|
||||
# type: (KMKKeyboard) -> None
|
||||
'''
|
||||
Return value will be injected as an extra matrix update
|
||||
'''
|
||||
raise NotImplementedError
|
||||
|
||||
def after_matrix_scan(self, keyboard):
|
||||
# type: (KMKKeyboard) -> None
|
||||
'''
|
||||
Return value will be replace matrix update if supplied
|
||||
'''
|
||||
raise NotImplementedError
|
||||
|
||||
def before_hid_send(self, keyboard):
|
||||
# type: (KMKKeyboard) -> None
|
||||
raise NotImplementedError
|
||||
|
||||
def after_hid_send(self, keyboard):
|
||||
# type: (KMKKeyboard) -> None
|
||||
raise NotImplementedError
|
||||
|
||||
def on_powersave_enable(self, keyboard):
|
||||
# type: (KMKKeyboard) -> None
|
||||
raise NotImplementedError
|
||||
|
||||
def on_powersave_disable(self, keyboard):
|
||||
# type: (KMKKeyboard) -> None
|
||||
raise NotImplementedError
|
||||
|
@@ -1,6 +1,7 @@
|
||||
'''Adds international keys'''
|
||||
from kmk.extensions import Extension
|
||||
from kmk.keys import make_key
|
||||
from kmk.kmk_keyboard import KMKKeyboard
|
||||
|
||||
|
||||
class International(Extension):
|
||||
@@ -32,28 +33,37 @@ class International(Extension):
|
||||
make_key(code=152, names=('LANG9',))
|
||||
|
||||
def on_runtime_enable(self, sandbox):
|
||||
# type: (KMKKeyboard) -> None
|
||||
return
|
||||
|
||||
def on_runtime_disable(self, sandbox):
|
||||
# type: (KMKKeyboard) -> None
|
||||
return
|
||||
|
||||
def during_bootup(self, sandbox):
|
||||
# type: (KMKKeyboard) -> None
|
||||
return
|
||||
|
||||
def before_matrix_scan(self, sandbox):
|
||||
# type: (KMKKeyboard) -> None
|
||||
return
|
||||
|
||||
def after_matrix_scan(self, sandbox):
|
||||
# type: (KMKKeyboard) -> None
|
||||
return
|
||||
|
||||
def before_hid_send(self, sandbox):
|
||||
# type: (KMKKeyboard) -> None
|
||||
return
|
||||
|
||||
def after_hid_send(self, sandbox):
|
||||
# type: (KMKKeyboard) -> None
|
||||
return
|
||||
|
||||
def on_powersave_enable(self, sandbox):
|
||||
# type: (KMKKeyboard) -> None
|
||||
return
|
||||
|
||||
def on_powersave_disable(self, sandbox):
|
||||
# type: (KMKKeyboard) -> None
|
||||
return
|
||||
|
@@ -1,11 +1,29 @@
|
||||
import sys
|
||||
from time import sleep
|
||||
|
||||
from kmk.consts import TYPING_PLATFORMS
|
||||
|
||||
if sys.platform in TYPING_PLATFORMS:
|
||||
from typing import Any, Optional
|
||||
|
||||
from kmk.keys import Key, KeyAttrDict
|
||||
from kmk.kmk_keyboard import KMKKeyboard # Avoid cyclical imports
|
||||
|
||||
|
||||
def passthrough(key, keyboard, *args, **kwargs):
|
||||
return keyboard
|
||||
|
||||
|
||||
def default_pressed(key, keyboard, KC, coord_int=None, coord_raw=None, *args, **kwargs):
|
||||
def default_pressed(
|
||||
key, # type: Key
|
||||
keyboard, # type: KMKKeyboard
|
||||
KC, # type: KeyAttrDict
|
||||
coord_int=None, # type: Optional[int]
|
||||
coord_raw=None, # type: Optional[str]
|
||||
*args, # type: Any
|
||||
**kwargs, # type: Any
|
||||
):
|
||||
# type: (...) -> KMKKeyboard
|
||||
keyboard.hid_pending = True
|
||||
|
||||
keyboard.keys_pressed.add(key)
|
||||
@@ -14,8 +32,15 @@ def default_pressed(key, keyboard, KC, coord_int=None, coord_raw=None, *args, **
|
||||
|
||||
|
||||
def default_released(
|
||||
key, keyboard, KC, coord_int=None, coord_raw=None, *args, **kwargs # NOQA
|
||||
key, # type: Key
|
||||
keyboard, # type: KMKKeyboard
|
||||
KC, # type: KeyAttrDict
|
||||
coord_int=None, # type: Optional[int]
|
||||
coord_raw=None, # type: Optional[str]
|
||||
*args, # type: Any
|
||||
**kwargs, # type: Any # NOQA
|
||||
):
|
||||
# type: (...) -> KMKKeyboard
|
||||
keyboard.hid_pending = True
|
||||
keyboard.keys_pressed.discard(key)
|
||||
|
||||
|
@@ -1,3 +1,6 @@
|
||||
import sys
|
||||
|
||||
from kmk.consts import TYPING_PLATFORMS
|
||||
from kmk.types import (
|
||||
KeySeqSleepMeta,
|
||||
LayerKeyMeta,
|
||||
@@ -6,12 +9,20 @@ from kmk.types import (
|
||||
UnicodeModeKeyMeta,
|
||||
)
|
||||
|
||||
if sys.platform in TYPING_PLATFORMS:
|
||||
from typing import List, Optional
|
||||
|
||||
# Avoid cyclical imports
|
||||
from kmk.keys import Key
|
||||
|
||||
|
||||
def key_seq_sleep_validator(ms):
|
||||
# type: (float) -> KeySeqSleepMeta
|
||||
return KeySeqSleepMeta(ms)
|
||||
|
||||
|
||||
def layer_key_validator(layer, kc=None):
|
||||
# type: (int, Optional[Key]) -> LayerKeyMeta
|
||||
'''
|
||||
Validates the syntax (but not semantics) of a layer key call. We won't
|
||||
have access to the keymap here, so we can't verify much of anything useful
|
||||
@@ -22,7 +33,8 @@ def layer_key_validator(layer, kc=None):
|
||||
return LayerKeyMeta(layer=layer, kc=kc)
|
||||
|
||||
|
||||
def mod_tap_validator(kc, mods=None):
|
||||
def mod_tap_validator(kc, mods):
|
||||
# type: (Key, Optional[List[Key]]) -> ModTapKeyMeta
|
||||
'''
|
||||
Validates that mod tap keys are correctly used
|
||||
'''
|
||||
@@ -30,8 +42,10 @@ def mod_tap_validator(kc, mods=None):
|
||||
|
||||
|
||||
def tap_dance_key_validator(*codes):
|
||||
# type: (*Key) -> TapDanceKeyMeta
|
||||
return TapDanceKeyMeta(codes)
|
||||
|
||||
|
||||
def unicode_mode_key_validator(mode):
|
||||
# type: (int) -> UnicodeModeKeyMeta
|
||||
return UnicodeModeKeyMeta(mode)
|
||||
|
@@ -1,3 +1,8 @@
|
||||
from typing import NoReturn
|
||||
|
||||
from kmk.kmk_keyboard import KMKKeyboard
|
||||
|
||||
|
||||
class InvalidExtensionEnvironment(Exception):
|
||||
pass
|
||||
|
||||
@@ -12,29 +17,29 @@ class Module:
|
||||
|
||||
# The below methods should be implemented by subclasses
|
||||
|
||||
def during_bootup(self, keyboard):
|
||||
def during_bootup(self, keyboard: KMKKeyboard) -> NoReturn:
|
||||
raise NotImplementedError
|
||||
|
||||
def before_matrix_scan(self, keyboard):
|
||||
def before_matrix_scan(self, keyboard: KMKKeyboard) -> NoReturn:
|
||||
'''
|
||||
Return value will be injected as an extra matrix update
|
||||
'''
|
||||
raise NotImplementedError
|
||||
|
||||
def after_matrix_scan(self, keyboard):
|
||||
def after_matrix_scan(self, keyboard: KMKKeyboard) -> NoReturn:
|
||||
'''
|
||||
Return value will be replace matrix update if supplied
|
||||
'''
|
||||
raise NotImplementedError
|
||||
|
||||
def before_hid_send(self, keyboard):
|
||||
def before_hid_send(self, keyboard: KMKKeyboard) -> NoReturn:
|
||||
raise NotImplementedError
|
||||
|
||||
def after_hid_send(self, keyboard):
|
||||
def after_hid_send(self, keyboard: KMKKeyboard) -> NoReturn:
|
||||
raise NotImplementedError
|
||||
|
||||
def on_powersave_enable(self, keyboard):
|
||||
def on_powersave_enable(self, keyboard: KMKKeyboard) -> NoReturn:
|
||||
raise NotImplementedError
|
||||
|
||||
def on_powersave_disable(self, keyboard):
|
||||
def on_powersave_disable(self, keyboard: KMKKeyboard) -> NoReturn:
|
||||
raise NotImplementedError
|
||||
|
@@ -1,66 +1,89 @@
|
||||
import digitalio
|
||||
from supervisor import ticks_ms
|
||||
|
||||
from typing import Any, ClassVar, Dict, List, Optional, Tuple, Union
|
||||
|
||||
from kmk.keys import Key
|
||||
from kmk.kmk_keyboard import KMKKeyboard
|
||||
from kmk.kmktime import ticks_ms
|
||||
from kmk.modules import Module
|
||||
|
||||
EncoderMap = Tuple[
|
||||
List[Tuple[Key, Key, int]],
|
||||
List[Tuple[Key, Key, int]],
|
||||
List[Tuple[None, None, int]],
|
||||
]
|
||||
|
||||
|
||||
class EncoderPadState:
|
||||
OFF = False
|
||||
ON = True
|
||||
OFF: bool = False
|
||||
ON: bool = True
|
||||
|
||||
|
||||
class EndcoderDirection:
|
||||
Left = False
|
||||
Right = True
|
||||
Left: bool = False
|
||||
Right: bool = True
|
||||
|
||||
|
||||
class Encoder:
|
||||
def __init__(
|
||||
self,
|
||||
pad_a,
|
||||
pad_b,
|
||||
button_pin=None,
|
||||
):
|
||||
self.pad_a = self.PreparePin(pad_a) # board pin for enc pin a
|
||||
self.pad_a_state = False
|
||||
self.pad_b = self.PreparePin(pad_b) # board pin for enc pin b
|
||||
self.pad_b_state = False
|
||||
self.button_pin = self.PreparePin(button_pin) # board pin for enc btn
|
||||
pad_a: Any,
|
||||
pad_b: Any,
|
||||
button_pin: Optional[Any] = None,
|
||||
) -> None:
|
||||
self.pad_a: Union[digitalio.DigitalInOut, None] = self.PreparePin(
|
||||
pad_a
|
||||
) # board pin for enc pin a
|
||||
self.pad_a_state: bool = False
|
||||
self.pad_b: Union[digitalio.DigitalInOut, None] = self.PreparePin(
|
||||
pad_b
|
||||
) # board pin for enc pin b
|
||||
self.pad_b_state: bool = False
|
||||
self.button_pin: Union[digitalio.DigitalInOut, None] = self.PreparePin(
|
||||
button_pin
|
||||
) # board pin for enc btn
|
||||
self.button_state = None # state of pushbutton on encoder if enabled
|
||||
self.encoder_value = 0 # clarify what this value is
|
||||
self.encoder_state = (
|
||||
self.encoder_value: int = 0 # clarify what this value is
|
||||
self.encoder_state: Tuple[bool, bool] = (
|
||||
self.pad_a_state,
|
||||
self.pad_b_state,
|
||||
) # quaderature encoder state
|
||||
self.encoder_direction = None # arbitrary, tells direction of knob
|
||||
self.last_encoder_state = None # not used yet
|
||||
self.resolution = 2 # number of keys sent per position change
|
||||
self.revolution_count = 20 # position changes per revolution
|
||||
self.has_button = False # enable/disable button functionality
|
||||
self.encoder_data = None # 6tuple containing all encoder data
|
||||
self.position_change = None # revolution count, inc/dec as knob turns
|
||||
self.last_encoder_value = 0 # not used
|
||||
self.is_inverted = False # switch to invert knob direction
|
||||
self.vel_mode = False # enable the velocity output
|
||||
self.vel_ts = None # velocity timestamp
|
||||
self.last_vel_ts = 0 # last velocity timestamp
|
||||
self.encoder_speed = None # ms per position change(4 states)
|
||||
self.encoder_map = None
|
||||
self.eps = EncoderPadState()
|
||||
self.encoder_pad_lookup = {
|
||||
self.encoder_direction: Optional[
|
||||
bool
|
||||
] = None # arbitrary, tells direction of knob
|
||||
self.last_encoder_state: Optional[Tuple[bool, bool]] = None # not used yet
|
||||
self.resolution: int = 2 # number of keys sent per position change
|
||||
self.revolution_count: int = 20 # position changes per revolution
|
||||
self.has_button: bool = False # enable/disable button functionality
|
||||
self.encoder_data: Optional[Tuple] = None # 6tuple containing all encoder data
|
||||
self.position_change: Optional[
|
||||
int
|
||||
] = None # revolution count, inc/dec as knob turns
|
||||
self.last_encoder_value: int = 0 # not used
|
||||
self.is_inverted: bool = False # switch to invert knob direction
|
||||
self.vel_mode: bool = False # enable the velocity output
|
||||
self.vel_ts: Optional[float] = None # velocity timestamp
|
||||
self.last_vel_ts: float = 0 # last velocity timestamp
|
||||
self.encoder_speed: Optional[float] = None # ms per position change(4 states)
|
||||
self.encoder_map: Optional[EncoderMap] = None
|
||||
self.eps: EncoderPadState = EncoderPadState()
|
||||
self.encoder_pad_lookup: Dict[bool, bool] = {
|
||||
False: self.eps.OFF,
|
||||
True: self.eps.ON,
|
||||
}
|
||||
self.edr = EndcoderDirection() # lookup for current encoder direction
|
||||
self.encoder_dir_lookup = {
|
||||
self.edr: EndcoderDirection = (
|
||||
EndcoderDirection()
|
||||
) # lookup for current encoder direction
|
||||
self.encoder_dir_lookup: Dict[bool, bool] = {
|
||||
False: self.edr.Left,
|
||||
True: self.edr.Right,
|
||||
}
|
||||
|
||||
def __repr__(self, idx):
|
||||
def __repr__(self, idx: int) -> str:
|
||||
return 'ENCODER_{}({})'.format(idx, self._to_dict())
|
||||
|
||||
def _to_dict(self):
|
||||
def _to_dict(self) -> Dict[str, Any]:
|
||||
return {
|
||||
'Encoder_State': self.encoder_state,
|
||||
'Direction': self.encoder_direction,
|
||||
@@ -71,7 +94,7 @@ class Encoder:
|
||||
}
|
||||
|
||||
# adapted for CircuitPython from raspi
|
||||
def PreparePin(self, num):
|
||||
def PreparePin(self, num: Union[Any, None]) -> Union[digitalio.DigitalInOut, None]:
|
||||
if num is not None:
|
||||
pad = digitalio.DigitalInOut(num)
|
||||
pad.direction = digitalio.Direction.INPUT
|
||||
@@ -81,7 +104,7 @@ class Encoder:
|
||||
return None
|
||||
|
||||
# checks encoder pins, reports encoder data
|
||||
def report(self):
|
||||
def report(self) -> Union[int, None]:
|
||||
new_encoder_state = (
|
||||
self.encoder_pad_lookup[int(self.pad_a.value)],
|
||||
self.encoder_pad_lookup[int(self.pad_b.value)],
|
||||
@@ -143,14 +166,14 @@ class Encoder:
|
||||
return None
|
||||
|
||||
# invert knob direction if encoder pins are soldered backwards
|
||||
def invert_rotation(self, new, old):
|
||||
def invert_rotation(self, new: int, old: int) -> int:
|
||||
if self.is_inverted:
|
||||
return -(new - old)
|
||||
else:
|
||||
return new - old
|
||||
|
||||
# returns knob velocity as milliseconds between position changes(detents)
|
||||
def vel_report(self):
|
||||
def vel_report(self) -> float:
|
||||
self.encoder_speed = self.vel_ts - self.last_vel_ts
|
||||
self.last_vel_ts = self.vel_ts
|
||||
return self.encoder_speed
|
||||
@@ -158,50 +181,54 @@ class Encoder:
|
||||
|
||||
class EncoderHandler(Module):
|
||||
|
||||
encoders = []
|
||||
debug_enabled = False # not working as inttended, do not use for now
|
||||
encoders: ClassVar[List[Encoder]] = []
|
||||
debug_enabled: ClassVar[
|
||||
bool
|
||||
] = False # not working as inttended, do not use for now
|
||||
|
||||
def __init__(self, pad_a, pad_b, encoder_map):
|
||||
self.pad_a = pad_a
|
||||
self.pad_b = pad_b
|
||||
self.encoder_count = len(self.pad_a)
|
||||
self.encoder_map = encoder_map
|
||||
def __init__(
|
||||
self, pad_a: List[Any], pad_b: List[Any], encoder_map: EncoderMap
|
||||
) -> None:
|
||||
self.pad_a: List[Any] = pad_a
|
||||
self.pad_b: List[Any] = pad_b
|
||||
self.encoder_count: int = len(self.pad_a)
|
||||
self.encoder_map: EncoderMap = encoder_map
|
||||
self.make_encoders()
|
||||
|
||||
def on_runtime_enable(self, keyboard):
|
||||
def on_runtime_enable(self, keyboard: KMKKeyboard) -> None:
|
||||
return
|
||||
|
||||
def on_runtime_disable(self, keyboard):
|
||||
def on_runtime_disable(self, keyboard: KMKKeyboard) -> None:
|
||||
return
|
||||
|
||||
def during_bootup(self, keyboard):
|
||||
def during_bootup(self, keyboard: KMKKeyboard) -> None:
|
||||
return
|
||||
|
||||
def before_matrix_scan(self, keyboard):
|
||||
def before_matrix_scan(self, keyboard: KMKKeyboard) -> Union[KMKKeyboard, None]:
|
||||
'''
|
||||
Return value will be injected as an extra matrix update
|
||||
'''
|
||||
return self.get_reports(keyboard)
|
||||
|
||||
def after_matrix_scan(self, keyboard):
|
||||
def after_matrix_scan(self, keyboard: KMKKeyboard) -> None:
|
||||
'''
|
||||
Return value will be replace matrix update if supplied
|
||||
'''
|
||||
return
|
||||
|
||||
def before_hid_send(self, keyboard):
|
||||
def before_hid_send(self, keyboard: KMKKeyboard) -> None:
|
||||
return
|
||||
|
||||
def after_hid_send(self, keyboard):
|
||||
def after_hid_send(self, keyboard: KMKKeyboard) -> None:
|
||||
return
|
||||
|
||||
def on_powersave_enable(self, keyboard):
|
||||
def on_powersave_enable(self, keyboard: KMKKeyboard) -> None:
|
||||
return
|
||||
|
||||
def on_powersave_disable(self, keyboard):
|
||||
def on_powersave_disable(self, keyboard: KMKKeyboard) -> None:
|
||||
return
|
||||
|
||||
def make_encoders(self):
|
||||
def make_encoders(self) -> None:
|
||||
for i in range(self.encoder_count):
|
||||
self.encoders.append(
|
||||
Encoder(
|
||||
@@ -210,7 +237,9 @@ class EncoderHandler(Module):
|
||||
)
|
||||
)
|
||||
|
||||
def send_encoder_keys(self, keyboard, encoder_key, encoder_idx):
|
||||
def send_encoder_keys(
|
||||
self, keyboard: KMKKeyboard, encoder_key: int, encoder_idx: int
|
||||
) -> KMKKeyboard:
|
||||
# position in the encoder map tuple
|
||||
encoder_resolution = 2
|
||||
for _ in range(
|
||||
@@ -221,7 +250,7 @@ class EncoderHandler(Module):
|
||||
)
|
||||
return keyboard
|
||||
|
||||
def get_reports(self, keyboard):
|
||||
def get_reports(self, keyboard: KMKKeyboard) -> Union[KMKKeyboard, None]:
|
||||
for idx in range(self.encoder_count):
|
||||
if self.debug_enabled: # not working as inttended, do not use for now
|
||||
print(self.encoders[idx].__repr__(idx))
|
||||
|
@@ -4,21 +4,24 @@ from supervisor import ticks_ms
|
||||
|
||||
from time import sleep
|
||||
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
from kmk.handlers.stock import passthrough as handler_passthrough
|
||||
from kmk.keys import make_key
|
||||
from kmk.keys import Key, make_key
|
||||
from kmk.kmk_keyboard import KMKKeyboard
|
||||
from kmk.kmktime import check_deadline
|
||||
from kmk.modules import Module
|
||||
|
||||
|
||||
class Power(Module):
|
||||
def __init__(self, powersave_pin=None):
|
||||
self.enable = False
|
||||
def __init__(self, powersave_pin: Optional[Any] = None) -> None:
|
||||
self.enable: bool = 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
|
||||
self._powersave_start: float = ticks_ms()
|
||||
self._usb_last_scan: float = ticks_ms() - 5000
|
||||
self._psp: Optional[digitalio.DigitalInOut] = None # Powersave pin object
|
||||
self._i2c: int = 0
|
||||
self._loopcounter: int = 0
|
||||
|
||||
make_key(
|
||||
names=('PS_TOG',), on_press=self._ps_tog, on_release=handler_passthrough
|
||||
@@ -30,10 +33,10 @@ class Power(Module):
|
||||
names=('PS_OFF',), on_press=self._ps_disable, on_release=handler_passthrough
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
def __repr__(self) -> str:
|
||||
return f'Power({self._to_dict()})'
|
||||
|
||||
def _to_dict(self):
|
||||
def _to_dict(self) -> Dict[str, Any]:
|
||||
return {
|
||||
'enable': self.enable,
|
||||
'powersave_pin': self.powersave_pin,
|
||||
@@ -42,24 +45,24 @@ class Power(Module):
|
||||
'_psp': self._psp,
|
||||
}
|
||||
|
||||
def during_bootup(self, keyboard):
|
||||
def during_bootup(self, keyboard: KMKKeyboard) -> None:
|
||||
self._i2c_scan()
|
||||
|
||||
def before_matrix_scan(self, keyboard):
|
||||
def before_matrix_scan(self, keyboard: KMKKeyboard) -> None:
|
||||
return
|
||||
|
||||
def after_matrix_scan(self, keyboard):
|
||||
def after_matrix_scan(self, keyboard: KMKKeyboard) -> None:
|
||||
if keyboard.matrix_update or keyboard.secondary_matrix_update:
|
||||
self.psave_time_reset()
|
||||
|
||||
def before_hid_send(self, keyboard):
|
||||
def before_hid_send(self, keyboard: KMKKeyboard) -> None:
|
||||
return
|
||||
|
||||
def after_hid_send(self, keyboard):
|
||||
def after_hid_send(self, keyboard: KMKKeyboard) -> None:
|
||||
if self.enable:
|
||||
self.psleep()
|
||||
|
||||
def on_powersave_enable(self, keyboard):
|
||||
def on_powersave_enable(self, keyboard: KMKKeyboard) -> None:
|
||||
'''Gives 10 cycles to allow other extensions to clean up before powersave'''
|
||||
if self._loopcounter > 10:
|
||||
self.enable_powersave(keyboard)
|
||||
@@ -68,11 +71,11 @@ class Power(Module):
|
||||
self._loopcounter += 1
|
||||
return
|
||||
|
||||
def on_powersave_disable(self, keyboard):
|
||||
def on_powersave_disable(self, keyboard: KMKKeyboard) -> None:
|
||||
self.disable_powersave(keyboard)
|
||||
return
|
||||
|
||||
def enable_powersave(self, keyboard):
|
||||
def enable_powersave(self, keyboard: KMKKeyboard) -> None:
|
||||
'''Enables power saving features'''
|
||||
if keyboard.i2c_deinit_count >= self._i2c and self.powersave_pin:
|
||||
# Allows power save to prevent RGB drain.
|
||||
@@ -88,7 +91,7 @@ class Power(Module):
|
||||
keyboard._trigger_powersave_enable = False
|
||||
return
|
||||
|
||||
def disable_powersave(self, keyboard):
|
||||
def disable_powersave(self, keyboard: KMKKeyboard) -> None:
|
||||
'''Disables power saving features'''
|
||||
if self._psp:
|
||||
self._psp.value = False
|
||||
@@ -99,7 +102,7 @@ class Power(Module):
|
||||
self.enable = False
|
||||
return
|
||||
|
||||
def psleep(self):
|
||||
def psleep(self) -> None:
|
||||
'''
|
||||
Sleeps longer and longer to save power the more time in between updates.
|
||||
'''
|
||||
@@ -109,10 +112,10 @@ class Power(Module):
|
||||
sleep(180 / 1000)
|
||||
return
|
||||
|
||||
def psave_time_reset(self):
|
||||
def psave_time_reset(self) -> None:
|
||||
self._powersave_start = ticks_ms()
|
||||
|
||||
def _i2c_scan(self):
|
||||
def _i2c_scan(self) -> None:
|
||||
i2c = board.I2C()
|
||||
while not i2c.try_lock():
|
||||
pass
|
||||
@@ -122,28 +125,46 @@ class Power(Module):
|
||||
i2c.unlock()
|
||||
return
|
||||
|
||||
def usb_rescan_timer(self):
|
||||
def usb_rescan_timer(self) -> bool:
|
||||
return bool(check_deadline(ticks_ms(), self._usb_last_scan) > 5000)
|
||||
|
||||
def usb_time_reset(self):
|
||||
def usb_time_reset(self) -> None:
|
||||
self._usb_last_scan = ticks_ms()
|
||||
return
|
||||
|
||||
def usb_scan(self):
|
||||
def usb_scan(self) -> bool:
|
||||
# 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):
|
||||
def _ps_tog(
|
||||
self,
|
||||
key: Key,
|
||||
keyboard: KMKKeyboard,
|
||||
*args: Any,
|
||||
**kwargs: Any,
|
||||
) -> None:
|
||||
if self.enable:
|
||||
keyboard._trigger_powersave_disable = True
|
||||
else:
|
||||
keyboard._trigger_powersave_enable = True
|
||||
|
||||
def _ps_enable(self, key, keyboard, *args, **kwargs):
|
||||
def _ps_enable(
|
||||
self,
|
||||
key: Key,
|
||||
keyboard: KMKKeyboard,
|
||||
*args: Any,
|
||||
**kwargs: Any,
|
||||
) -> None:
|
||||
if not self.enable:
|
||||
keyboard._trigger_powersave_enable = True
|
||||
|
||||
def _ps_disable(self, key, keyboard, *args, **kwargs):
|
||||
def _ps_disable(
|
||||
self,
|
||||
key: Key,
|
||||
keyboard: KMKKeyboard,
|
||||
*args: Any,
|
||||
**kwargs: Any,
|
||||
) -> None:
|
||||
if self.enable:
|
||||
keyboard._trigger_powersave_disable = True
|
||||
|
@@ -4,22 +4,26 @@ from micropython import const
|
||||
from supervisor import ticks_ms
|
||||
|
||||
from storage import getmount
|
||||
from typing import Any, List, Optional, Type, Union
|
||||
|
||||
from kmk.kmk_keyboard import KMKKeyboard
|
||||
from kmk.kmktime import check_deadline
|
||||
from kmk.matrix import intify_coordinate
|
||||
from kmk.modules import Module
|
||||
|
||||
UartBuffer = List[Optional[Union[bytes, None]]]
|
||||
|
||||
|
||||
class SplitSide:
|
||||
LEFT = const(1)
|
||||
RIGHT = const(2)
|
||||
LEFT: int = const(1)
|
||||
RIGHT: int = const(2)
|
||||
|
||||
|
||||
class SplitType:
|
||||
UART = const(1)
|
||||
I2C = const(2) # unused
|
||||
ONEWIRE = const(3) # unused
|
||||
BLE = const(4)
|
||||
UART: int = const(1)
|
||||
I2C: int = const(2) # unused
|
||||
ONEWIRE: int = const(3) # unused
|
||||
BLE: int = const(4)
|
||||
|
||||
|
||||
class Split(Module):
|
||||
@@ -27,56 +31,58 @@ class Split(Module):
|
||||
|
||||
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,
|
||||
debug_enabled=False,
|
||||
):
|
||||
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 = debug_enabled
|
||||
split_flip: bool = True,
|
||||
split_side: Optional[int] = None,
|
||||
split_type: int = SplitType.UART,
|
||||
split_target_left: bool = True,
|
||||
uart_interval: int = 20,
|
||||
data_pin: Optional[Any] = None,
|
||||
data_pin2: Optional[Any] = None,
|
||||
target_left: bool = True,
|
||||
uart_flip: bool = True,
|
||||
debug_enabled: bool = False,
|
||||
) -> None:
|
||||
self._is_target: bool = True
|
||||
self._uart_buffer: UartBuffer = []
|
||||
self.split_flip: bool = split_flip
|
||||
self.split_side: Optional[int] = split_side
|
||||
self.split_type: int = split_type
|
||||
self.split_target_left: bool = split_target_left
|
||||
self.split_offset: Optional[int] = None
|
||||
self.data_pin: Optional[Any] = data_pin
|
||||
self.data_pin2: Optional[Any] = data_pin2
|
||||
self.target_left: bool = target_left
|
||||
self.uart_flip: bool = uart_flip
|
||||
self._is_target: bool = True
|
||||
self._uart: Optional[busio.UART] = None
|
||||
self._uart_interval: int = uart_interval
|
||||
self._debug_enabled: bool = debug_enabled
|
||||
if self.split_type == SplitType.BLE:
|
||||
try:
|
||||
from adafruit_ble import BLERadio
|
||||
from adafruit_ble import BLEConnection, BLERadio
|
||||
from adafruit_ble.advertising.standard import (
|
||||
ProvideServicesAdvertisement,
|
||||
)
|
||||
from adafruit_ble.services.nordic import UARTService
|
||||
|
||||
self.ProvideServicesAdvertisement = ProvideServicesAdvertisement
|
||||
self.UARTService = UARTService
|
||||
self.ProvideServicesAdvertisement: Type[
|
||||
ProvideServicesAdvertisement
|
||||
] = ProvideServicesAdvertisement
|
||||
self.UARTService: Type[UARTService] = UARTService
|
||||
except ImportError:
|
||||
print('BLE Import error')
|
||||
return # 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
|
||||
self._ble: BLERadio = BLERadio()
|
||||
self._ble_last_scan: float = ticks_ms() - 5000
|
||||
self._connection_count: int = 0
|
||||
self._uart_connection: Optional[BLEConnection] = None
|
||||
self._advertisment: Optional[ProvideServicesAdvertisement] = None
|
||||
self._advertising: bool = False
|
||||
self._psave_enable: bool = False
|
||||
|
||||
def during_bootup(self, keyboard):
|
||||
def during_bootup(self, keyboard: KMKKeyboard) -> None:
|
||||
# Set up name for target side detection and BLE advertisment
|
||||
name = str(getmount('/').label)
|
||||
name: str = str(getmount('/').label)
|
||||
if self.split_type == SplitType.BLE:
|
||||
self._ble.name = name
|
||||
else:
|
||||
@@ -128,7 +134,7 @@ class Split(Module):
|
||||
for cidx in range(cols_to_calc):
|
||||
keyboard.coord_mapping.append(intify_coordinate(ridx, cidx))
|
||||
|
||||
def before_matrix_scan(self, keyboard):
|
||||
def before_matrix_scan(self, keyboard: KMKKeyboard) -> None:
|
||||
if self.split_type == SplitType.BLE:
|
||||
self._check_all_connections()
|
||||
self._receive_ble(keyboard)
|
||||
@@ -139,7 +145,7 @@ class Split(Module):
|
||||
pass # Protocol needs written
|
||||
return
|
||||
|
||||
def after_matrix_scan(self, keyboard):
|
||||
def after_matrix_scan(self, keyboard: KMKKeyboard) -> None:
|
||||
if keyboard.matrix_update:
|
||||
if self.split_type == SplitType.UART and self._is_target:
|
||||
pass # explicit pass just for dev sanity...
|
||||
@@ -156,28 +162,28 @@ class Split(Module):
|
||||
|
||||
return
|
||||
|
||||
def before_hid_send(self, keyboard):
|
||||
def before_hid_send(self, keyboard: KMKKeyboard) -> None:
|
||||
if not self._is_target:
|
||||
keyboard.hid_pending = False
|
||||
|
||||
return
|
||||
|
||||
def after_hid_send(self, keyboard):
|
||||
def after_hid_send(self, keyboard: KMKKeyboard) -> None:
|
||||
return
|
||||
|
||||
def on_powersave_enable(self, keyboard):
|
||||
def on_powersave_enable(self, keyboard: KMKKeyboard) -> None:
|
||||
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):
|
||||
def on_powersave_disable(self, keyboard: KMKKeyboard) -> None:
|
||||
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):
|
||||
def _check_all_connections(self) -> None:
|
||||
'''Validates the correct number of BLE connections'''
|
||||
self._connection_count = len(self._ble.connections)
|
||||
if self._is_target and self._connection_count < 2:
|
||||
@@ -185,7 +191,7 @@ class Split(Module):
|
||||
elif not self._is_target and self._connection_count < 1:
|
||||
self._initiator_scan()
|
||||
|
||||
def _initiator_scan(self):
|
||||
def _initiator_scan(self) -> None:
|
||||
'''Scans for target device'''
|
||||
self._uart = None
|
||||
self._uart_connection = None
|
||||
@@ -218,7 +224,7 @@ class Split(Module):
|
||||
break
|
||||
self._ble.stop_scan()
|
||||
|
||||
def _target_advertise(self):
|
||||
def _target_advertise(self) -> None:
|
||||
'''Advertises the target for the initiator to find'''
|
||||
self._ble.stop_advertising()
|
||||
if self._debug_enabled:
|
||||
@@ -240,15 +246,15 @@ class Split(Module):
|
||||
break
|
||||
self._ble.stop_advertising()
|
||||
|
||||
def ble_rescan_timer(self):
|
||||
def ble_rescan_timer(self) -> bool:
|
||||
'''If true, the rescan timer is up'''
|
||||
return bool(check_deadline(ticks_ms(), self._ble_last_scan) > 5000)
|
||||
|
||||
def ble_time_reset(self):
|
||||
def ble_time_reset(self) -> None:
|
||||
'''Resets the rescan timer'''
|
||||
self._ble_last_scan = ticks_ms()
|
||||
|
||||
def _send_ble(self, update):
|
||||
def _send_ble(self, update: List) -> None:
|
||||
if self._uart:
|
||||
try:
|
||||
if not self._is_target:
|
||||
@@ -266,7 +272,7 @@ class Split(Module):
|
||||
self._uart_connection = None
|
||||
self._uart = None
|
||||
|
||||
def _receive_ble(self, keyboard):
|
||||
def _receive_ble(self, keyboard: KMKKeyboard) -> None:
|
||||
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))
|
||||
@@ -274,7 +280,7 @@ class Split(Module):
|
||||
keyboard.secondary_matrix_update = bytearray(self._uart_buffer.pop(0))
|
||||
return
|
||||
|
||||
def _send_uart(self, update):
|
||||
def _send_uart(self, update: List) -> None:
|
||||
# Change offsets depending on where the data is going to match the correct
|
||||
# matrix location of the receiever
|
||||
if self._is_target:
|
||||
@@ -291,7 +297,7 @@ class Split(Module):
|
||||
if self._uart is not None:
|
||||
self._uart.write(update)
|
||||
|
||||
def _receive_uart(self, keyboard):
|
||||
def _receive_uart(self, keyboard: KMKKeyboard) -> None:
|
||||
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
|
||||
|
34
kmk/types.py
34
kmk/types.py
@@ -1,3 +1,14 @@
|
||||
import sys
|
||||
|
||||
from kmk.consts import TYPING_PLATFORMS
|
||||
|
||||
if sys.platform in TYPING_PLATFORMS:
|
||||
from typing import List, Optional, Tuple, Union
|
||||
|
||||
# Avoid cyclical imports
|
||||
from kmk.keys import ConsumerKey, Key, ModifierKey
|
||||
|
||||
|
||||
class AttrDict(dict):
|
||||
'''
|
||||
Primitive support for accessing dictionary entries in dot notation.
|
||||
@@ -8,36 +19,43 @@ class AttrDict(dict):
|
||||
'''
|
||||
|
||||
def __getattr__(self, key):
|
||||
# type: (str) -> Optional[Union[Key, ModifierKey, ConsumerKey]]
|
||||
return self[key]
|
||||
|
||||
|
||||
class LayerKeyMeta:
|
||||
def __init__(self, layer, kc=None):
|
||||
self.layer = layer
|
||||
self.kc = kc
|
||||
# type: (int, Optional[Key]) -> None
|
||||
self.layer = layer # type: int
|
||||
self.kc = kc # type: Optional[Key]
|
||||
|
||||
|
||||
class ModTapKeyMeta:
|
||||
def __init__(self, kc=None, mods=None):
|
||||
self.mods = mods
|
||||
self.kc = kc
|
||||
# type: (Optional[Key], Optional[List[Key]]) -> None
|
||||
self.mods = mods # type: Optional[List[Key]]
|
||||
self.kc = kc # type: Optional[Key]
|
||||
|
||||
|
||||
class KeySequenceMeta:
|
||||
def __init__(self, seq):
|
||||
self.seq = seq
|
||||
# type: (List[Key]) -> None
|
||||
self.seq = seq # type: List[Key]
|
||||
|
||||
|
||||
class KeySeqSleepMeta:
|
||||
def __init__(self, ms):
|
||||
self.ms = ms
|
||||
# type: (float) -> None
|
||||
self.ms = ms # type: float
|
||||
|
||||
|
||||
class UnicodeModeKeyMeta:
|
||||
def __init__(self, mode):
|
||||
self.mode = mode
|
||||
# type: (int) -> None
|
||||
self.mode = mode # type: int
|
||||
|
||||
|
||||
class TapDanceKeyMeta:
|
||||
def __init__(self, codes):
|
||||
self.codes = codes
|
||||
# type: (Tuple[Key, ...]) -> None
|
||||
self.codes = codes # type: Tuple[Key, ...]
|
||||
|
Reference in New Issue
Block a user