massive cleanup
This commit is contained in:
@@ -18,28 +18,28 @@ class Extension:
|
||||
# The below methods should be implemented by subclasses
|
||||
|
||||
def on_runtime_enable(self, keyboard):
|
||||
pass
|
||||
raise NotImplementedError
|
||||
|
||||
def on_runtime_disable(self, keyboard):
|
||||
pass
|
||||
raise NotImplementedError
|
||||
|
||||
def during_bootup(self, keyboard):
|
||||
pass
|
||||
raise NotImplementedError
|
||||
|
||||
def before_matrix_scan(self, keyboard):
|
||||
'''
|
||||
Return value will be injected as an extra matrix update
|
||||
'''
|
||||
pass
|
||||
raise NotImplementedError
|
||||
|
||||
def after_matrix_scan(self, keyboard, matrix_update):
|
||||
'''
|
||||
Return value will be replace matrix update if supplied
|
||||
'''
|
||||
pass
|
||||
raise NotImplementedError
|
||||
|
||||
def before_hid_send(self, keyboard):
|
||||
pass
|
||||
raise NotImplementedError
|
||||
|
||||
def after_hid_send(self, keyboard):
|
||||
pass
|
||||
raise NotImplementedError
|
||||
|
@@ -1,8 +1,11 @@
|
||||
'''Adds international keys'''
|
||||
from kmk.extensions import Extension
|
||||
from kmk.keys import make_key
|
||||
|
||||
|
||||
class International(Extension):
|
||||
'''Adds international keys'''
|
||||
|
||||
def __init__(self):
|
||||
# International
|
||||
make_key(code=50, names=('NONUS_HASH', 'NUHS'))
|
||||
@@ -27,3 +30,24 @@ class International(Extension):
|
||||
make_key(code=150, names=('LANG7',))
|
||||
make_key(code=151, names=('LANG8',))
|
||||
make_key(code=152, names=('LANG9',))
|
||||
|
||||
def on_runtime_enable(self, keyboard):
|
||||
return
|
||||
|
||||
def on_runtime_disable(self, keyboard):
|
||||
return
|
||||
|
||||
def during_bootup(self, keyboard):
|
||||
return
|
||||
|
||||
def before_matrix_scan(self, keyboard):
|
||||
return
|
||||
|
||||
def after_matrix_scan(self, keyboard, matrix_update):
|
||||
return
|
||||
|
||||
def before_hid_send(self, keyboard):
|
||||
return
|
||||
|
||||
def after_hid_send(self, keyboard):
|
||||
return
|
||||
|
@@ -1,14 +1,15 @@
|
||||
'''One layer isn't enough. Adds keys to get to more of them'''
|
||||
from micropython import const
|
||||
|
||||
import kmk.handlers.modtap as modtap
|
||||
from kmk.extensions import Extension
|
||||
from kmk.key_validators import layer_key_validator, mod_tap_validator
|
||||
from kmk.key_validators import layer_key_validator
|
||||
from kmk.keys import make_argumented_key
|
||||
from kmk.kmktime import accurate_ticks, accurate_ticks_diff
|
||||
|
||||
|
||||
class LayerType:
|
||||
# These number must be reserved for layer timers.
|
||||
'''Defines layer type values for readability'''
|
||||
|
||||
MO = const(0)
|
||||
DF = const(1)
|
||||
LM = const(2)
|
||||
@@ -18,47 +19,42 @@ class LayerType:
|
||||
|
||||
|
||||
class Layers(Extension):
|
||||
'''Gives access to the keys used to enable the layer system'''
|
||||
|
||||
def __init__(self):
|
||||
# Layers
|
||||
make_argumented_key(
|
||||
validator=layer_key_validator,
|
||||
names=('MO',),
|
||||
on_press=self.mo_pressed,
|
||||
on_release=self.mo_released,
|
||||
on_press=self._mo_pressed,
|
||||
on_release=self._mo_released,
|
||||
)
|
||||
make_argumented_key(
|
||||
validator=layer_key_validator, names=('DF',), on_press=self.df_pressed
|
||||
validator=layer_key_validator, names=('DF',), on_press=self._df_pressed
|
||||
)
|
||||
make_argumented_key(
|
||||
validator=layer_key_validator,
|
||||
names=('LM',),
|
||||
on_press=self.lm_pressed,
|
||||
on_release=self.lm_released,
|
||||
on_press=self._lm_pressed,
|
||||
on_release=self._lm_released,
|
||||
)
|
||||
make_argumented_key(
|
||||
validator=layer_key_validator,
|
||||
names=('LT',),
|
||||
on_press=self.lt_pressed,
|
||||
on_release=self.lt_released,
|
||||
on_press=self._lt_pressed,
|
||||
on_release=self._lt_released,
|
||||
)
|
||||
make_argumented_key(
|
||||
validator=layer_key_validator, names=('TG',), on_press=self.tg_pressed
|
||||
validator=layer_key_validator, names=('TG',), on_press=self._tg_pressed
|
||||
)
|
||||
make_argumented_key(
|
||||
validator=layer_key_validator, names=('TO',), on_press=self.to_pressed
|
||||
validator=layer_key_validator, names=('TO',), on_press=self._to_pressed
|
||||
)
|
||||
make_argumented_key(
|
||||
validator=layer_key_validator,
|
||||
names=('TT',),
|
||||
on_press=self.tt_pressed,
|
||||
on_release=self.tt_released,
|
||||
)
|
||||
|
||||
make_argumented_key(
|
||||
validator=mod_tap_validator,
|
||||
names=('MT',),
|
||||
on_press=modtap.mt_pressed,
|
||||
on_release=modtap.mt_released,
|
||||
on_press=self._tt_pressed,
|
||||
on_release=self._tt_released,
|
||||
)
|
||||
|
||||
start_time = {
|
||||
@@ -68,21 +64,45 @@ class Layers(Extension):
|
||||
LayerType.LM: None,
|
||||
}
|
||||
|
||||
def df_pressed(self, key, state, *args, **kwargs):
|
||||
def on_runtime_enable(self, keyboard):
|
||||
return
|
||||
|
||||
def on_runtime_disable(self, keyboard):
|
||||
return
|
||||
|
||||
def during_bootup(self, keyboard):
|
||||
return
|
||||
|
||||
def before_matrix_scan(self, keyboard):
|
||||
return
|
||||
|
||||
def after_matrix_scan(self, keyboard, matrix_update):
|
||||
return
|
||||
|
||||
def before_hid_send(self, keyboard):
|
||||
return
|
||||
|
||||
def _after_hid_send(self, keyboard):
|
||||
return
|
||||
|
||||
@staticmethod
|
||||
def _df_pressed(key, state, *args, **kwargs):
|
||||
'''
|
||||
Switches the default layer
|
||||
'''
|
||||
state._active_layers[-1] = key.meta.layer
|
||||
state.active_layers[-1] = key.meta.layer
|
||||
return state
|
||||
|
||||
def mo_pressed(self, key, state, *args, **kwargs):
|
||||
@staticmethod
|
||||
def _mo_pressed(key, state, *args, **kwargs):
|
||||
'''
|
||||
Momentarily activates layer, switches off when you let go
|
||||
'''
|
||||
state._active_layers.insert(0, key.meta.layer)
|
||||
state.active_layers.insert(0, key.meta.layer)
|
||||
return state
|
||||
|
||||
def mo_released(self, key, state, KC, *args, **kwargs):
|
||||
@staticmethod
|
||||
def _mo_released(key, state, KC, *args, **kwargs):
|
||||
# remove the first instance of the target layer
|
||||
# from the active list
|
||||
# under almost all normal use cases, this will
|
||||
@@ -92,93 +112,95 @@ class Layers(Extension):
|
||||
# triggered by MO() and then defaulting to the MO()'s layer
|
||||
# would result in no layers active
|
||||
try:
|
||||
del_idx = state._active_layers.index(key.meta.layer)
|
||||
del state._active_layers[del_idx]
|
||||
del_idx = state.active_layers.index(key.meta.layer)
|
||||
del state.active_layers[del_idx]
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
return state
|
||||
|
||||
def lm_pressed(self, key, state, *args, **kwargs):
|
||||
def _lm_pressed(self, key, state, *args, **kwargs):
|
||||
'''
|
||||
As MO(layer) but with mod active
|
||||
'''
|
||||
state._hid_pending = True
|
||||
state.hid_pending = True
|
||||
# Sets the timer start and acts like MO otherwise
|
||||
state._keys_pressed.add(key.meta.kc)
|
||||
return self.mo_pressed(key, state, *args, **kwargs)
|
||||
state.keys_pressed.add(key.meta.kc)
|
||||
return self._mo_pressed(key, state, *args, **kwargs)
|
||||
|
||||
def lm_released(self, key, state, *args, **kwargs):
|
||||
def _lm_released(self, key, state, *args, **kwargs):
|
||||
'''
|
||||
As MO(layer) but with mod active
|
||||
'''
|
||||
state._hid_pending = True
|
||||
state._keys_pressed.discard(key.meta.kc)
|
||||
return self.mo_released(key, state, *args, **kwargs)
|
||||
state.hid_pending = True
|
||||
state.keys_pressed.discard(key.meta.kc)
|
||||
return self._mo_released(key, state, *args, **kwargs)
|
||||
|
||||
def lt_pressed(self, key, state, *args, **kwargs):
|
||||
def _lt_pressed(self, key, state, *args, **kwargs):
|
||||
# Sets the timer start and acts like MO otherwise
|
||||
self.start_time[LayerType.LT] = accurate_ticks()
|
||||
return self.mo_pressed(key, state, *args, **kwargs)
|
||||
return self._mo_pressed(key, state, *args, **kwargs)
|
||||
|
||||
def lt_released(self, key, state, *args, **kwargs):
|
||||
def _lt_released(self, key, state, *args, **kwargs):
|
||||
# On keyup, check timer, and press key if needed.
|
||||
if self.start_time[LayerType.LT] and (
|
||||
accurate_ticks_diff(
|
||||
accurate_ticks(), self.start_time[LayerType.LT], state.tap_time
|
||||
)
|
||||
):
|
||||
state._hid_pending = True
|
||||
state._tap_key(key.meta.kc)
|
||||
state.hid_pending = True
|
||||
state.tap_key(key.meta.kc)
|
||||
|
||||
self.mo_released(key, state, *args, **kwargs)
|
||||
self._mo_released(key, state, *args, **kwargs)
|
||||
self.start_time[LayerType.LT] = None
|
||||
return state
|
||||
|
||||
def tg_pressed(self, key, state, *args, **kwargs):
|
||||
@staticmethod
|
||||
def _tg_pressed(key, state, *args, **kwargs):
|
||||
'''
|
||||
Toggles the layer (enables it if not active, and vise versa)
|
||||
'''
|
||||
# See mo_released for implementation details around this
|
||||
try:
|
||||
del_idx = state._active_layers.index(key.meta.layer)
|
||||
del state._active_layers[del_idx]
|
||||
del_idx = state.active_layers.index(key.meta.layer)
|
||||
del state.active_layers[del_idx]
|
||||
except ValueError:
|
||||
state._active_layers.insert(0, key.meta.layer)
|
||||
state.active_layers.insert(0, key.meta.layer)
|
||||
|
||||
return state
|
||||
|
||||
def to_pressed(self, key, state, *args, **kwargs):
|
||||
@staticmethod
|
||||
def _to_pressed(key, state, *args, **kwargs):
|
||||
'''
|
||||
Activates layer and deactivates all other layers
|
||||
'''
|
||||
state._active_layers.clear()
|
||||
state._active_layers.insert(0, key.meta.layer)
|
||||
state.active_layers.clear()
|
||||
state.active_layers.insert(0, key.meta.layer)
|
||||
|
||||
return state
|
||||
|
||||
def tt_pressed(self, key, state, *args, **kwargs):
|
||||
def _tt_pressed(self, key, state, *args, **kwargs):
|
||||
'''
|
||||
Momentarily activates layer if held, toggles it if tapped repeatedly
|
||||
'''
|
||||
# TODO Make this work with tap dance to function more correctly, but technically works.
|
||||
if self.start_time[LayerType.TT] is None:
|
||||
# Sets the timer start and acts like MO otherwise
|
||||
self.start_time[LayerType.TT] = accurate_ticks()
|
||||
return self.mo_pressed(key, state, *args, **kwargs)
|
||||
return self._mo_pressed(key, state, *args, **kwargs)
|
||||
elif accurate_ticks_diff(
|
||||
accurate_ticks(), self.start_time[LayerType.TT], state.tap_time
|
||||
):
|
||||
self.start_time[LayerType.TT] = None
|
||||
return self.tg_pressed(key, state, *args, **kwargs)
|
||||
return self._tg_pressed(key, state, *args, **kwargs)
|
||||
return None
|
||||
|
||||
def tt_released(self, key, state, *args, **kwargs):
|
||||
def _tt_released(self, key, state, *args, **kwargs):
|
||||
if self.start_time[LayerType.TT] is None or not accurate_ticks_diff(
|
||||
accurate_ticks(), self.start_time[LayerType.TT], state.tap_time
|
||||
):
|
||||
# On first press, works like MO. On second press, does nothing unless let up within
|
||||
# time window, then acts like TG.
|
||||
self.start_time[LayerType.TT] = None
|
||||
return self.mo_released(key, state, *args, **kwargs)
|
||||
return self._mo_released(key, state, *args, **kwargs)
|
||||
|
||||
return state
|
||||
|
@@ -31,24 +31,35 @@ class Leader(Extension):
|
||||
on_release=handler_passthrough,
|
||||
)
|
||||
|
||||
def after_matrix_scan(self, keyboard_state, *args):
|
||||
def on_runtime_enable(self, keyboard):
|
||||
return
|
||||
|
||||
def on_runtime_disable(self, keyboard):
|
||||
return
|
||||
|
||||
def during_bootup(self, keyboard):
|
||||
return
|
||||
|
||||
def before_matrix_scan(self, keyboard):
|
||||
return
|
||||
|
||||
def after_matrix_scan(self, keyboard, matrix_update):
|
||||
if self._mode % 2 == 1:
|
||||
keys_pressed = keyboard_state._keys_pressed
|
||||
keys_pressed = keyboard.keys_pressed
|
||||
|
||||
if self._assembly_last_len and self._sequence_assembly:
|
||||
history_set = set(self._sequence_assembly)
|
||||
|
||||
keys_pressed = keys_pressed - history_set
|
||||
|
||||
self._assembly_last_len = len(keyboard_state._keys_pressed)
|
||||
self._assembly_last_len = len(keyboard.keys_pressed)
|
||||
|
||||
for key in keys_pressed:
|
||||
if self._mode == LeaderMode.ENTER_ACTIVE and key == KC.ENT:
|
||||
self._handle_leader_sequence(keyboard_state)
|
||||
break
|
||||
elif key == KC.ESC or key == KC.GESC:
|
||||
self._handle_leader_sequence(keyboard)
|
||||
elif key in (KC.ESC, KC.GESC):
|
||||
# Clean self and turn leader mode off.
|
||||
self._exit_leader_mode(keyboard_state)
|
||||
self._exit_leader_mode(keyboard)
|
||||
break
|
||||
elif key == KC.LEAD:
|
||||
break
|
||||
@@ -57,9 +68,16 @@ class Leader(Extension):
|
||||
# This needs replaced later with a proper debounce
|
||||
self._sequence_assembly.append(key)
|
||||
|
||||
keyboard_state._hid_pending = False
|
||||
keyboard.hid_pending = False
|
||||
|
||||
def _compile_sequences(self, sequences):
|
||||
def before_hid_send(self, keyboard):
|
||||
return
|
||||
|
||||
def after_hid_send(self, keyboard):
|
||||
return
|
||||
|
||||
@staticmethod
|
||||
def _compile_sequences(sequences):
|
||||
|
||||
for k, v in sequences.items():
|
||||
if not isinstance(k, tuple):
|
||||
@@ -72,33 +90,33 @@ class Leader(Extension):
|
||||
|
||||
return sequences
|
||||
|
||||
def _handle_leader_sequence(self, keyboard_state):
|
||||
def _handle_leader_sequence(self, keyboard):
|
||||
lmh = tuple(self._sequence_assembly)
|
||||
# Will get caught in infinite processing loops if we don't
|
||||
# exit leader mode before processing the target key
|
||||
self._exit_leader_mode(keyboard_state)
|
||||
self._exit_leader_mode(keyboard)
|
||||
|
||||
if lmh in self._sequences:
|
||||
# Stack depth exceeded if try to use add_key here with a unicode sequence
|
||||
keyboard_state._process_key(self._sequences[lmh], True)
|
||||
keyboard.process_key(self._sequences[lmh], True)
|
||||
|
||||
keyboard_state._set_timeout(
|
||||
False, lambda: keyboard_state._remove_key(self._sequences[lmh])
|
||||
keyboard.set_timeout(
|
||||
False, lambda: keyboard.remove_key(self._sequences[lmh])
|
||||
)
|
||||
|
||||
def _exit_leader_mode(self, keyboard_state):
|
||||
def _exit_leader_mode(self, keyboard):
|
||||
self._sequence_assembly.clear()
|
||||
self._mode -= 1
|
||||
self._assembly_last_len = 0
|
||||
keyboard_state._keys_pressed.clear()
|
||||
keyboard.keys_pressed.clear()
|
||||
|
||||
def _key_leader_pressed(self, key, keyboard_state, *args, **kwargs):
|
||||
def _key_leader_pressed(self, key, keyboard):
|
||||
if self._mode % 2 == 0:
|
||||
keyboard_state._keys_pressed.discard(key)
|
||||
keyboard.keys_pressed.discard(key)
|
||||
# All leader modes are one number higher when activating
|
||||
self._mode += 1
|
||||
|
||||
if self._mode == LeaderMode.TIMEOUT_ACTIVE:
|
||||
keyboard_state._set_timeout(
|
||||
self._timeout, lambda: self._handle_leader_sequence(keyboard_state)
|
||||
keyboard.set_timeout(
|
||||
self._timeout, lambda: self._handle_leader_sequence(keyboard)
|
||||
)
|
||||
|
@@ -66,10 +66,23 @@ class LED(Extension):
|
||||
def _to_dict(self):
|
||||
return f'LED(_brightness={self._brightness} _pos={self._pos} brightness_step={self.brightness_step} brightness_limit={self.brightness_limit} animation_mode={self.animation_mode} animation_speed={self.animation_speed} breathe_center={self.breathe_center} val={self.val} )'
|
||||
|
||||
def _init_effect(self):
|
||||
self._pos = 0
|
||||
self._effect_init = False
|
||||
return self
|
||||
def on_runtime_enable(self, keyboard):
|
||||
return
|
||||
|
||||
def on_runtime_disable(self, keyboard):
|
||||
return
|
||||
|
||||
def during_bootup(self, keyboard):
|
||||
return
|
||||
|
||||
def before_matrix_scan(self, keyboard):
|
||||
return
|
||||
|
||||
def after_matrix_scan(self, keyboard, matrix_update):
|
||||
return
|
||||
|
||||
def before_hid_send(self, keyboard):
|
||||
return
|
||||
|
||||
def after_hid_send(self, keyboard):
|
||||
if self._enabled and self.animation_mode:
|
||||
@@ -77,6 +90,11 @@ class LED(Extension):
|
||||
|
||||
return keyboard
|
||||
|
||||
def _init_effect(self):
|
||||
self._pos = 0
|
||||
self._effect_init = False
|
||||
return self
|
||||
|
||||
def set_brightness(self, percent):
|
||||
self._led.duty_cycle = int(percent / 100 * 65535)
|
||||
|
||||
@@ -161,8 +179,6 @@ class LED(Extension):
|
||||
else:
|
||||
self.off()
|
||||
|
||||
return self
|
||||
|
||||
def _key_led_tog(self, key, state, *args, **kwargs):
|
||||
if self.animation_mode == AnimationModes.STATIC_STANDBY:
|
||||
self.animation_mode = AnimationModes.STATIC
|
||||
|
@@ -26,3 +26,24 @@ class MediaKeys(Extension):
|
||||
make_consumer_key(code=184, names=('MEDIA_EJECT', 'EJCT')) # 0xB8
|
||||
make_consumer_key(code=179, names=('MEDIA_FAST_FORWARD', 'MFFD')) # 0xB3
|
||||
make_consumer_key(code=180, names=('MEDIA_REWIND', 'MRWD')) # 0xB4
|
||||
|
||||
def on_runtime_enable(self, keyboard):
|
||||
return
|
||||
|
||||
def on_runtime_disable(self, keyboard):
|
||||
return
|
||||
|
||||
def during_bootup(self, keyboard):
|
||||
return
|
||||
|
||||
def before_matrix_scan(self, keyboard):
|
||||
return
|
||||
|
||||
def after_matrix_scan(self, keyboard, matrix_update):
|
||||
return
|
||||
|
||||
def before_hid_send(self, keyboard):
|
||||
return
|
||||
|
||||
def after_hid_send(self, keyboard):
|
||||
return
|
||||
|
55
kmk/extensions/modtap.py
Normal file
55
kmk/extensions/modtap.py
Normal file
@@ -0,0 +1,55 @@
|
||||
from kmk.extensions import Extension
|
||||
from kmk.key_validators import mod_tap_validator
|
||||
from kmk.keys import make_argumented_key
|
||||
from kmk.kmktime import accurate_ticks, accurate_ticks_diff
|
||||
|
||||
|
||||
class ModTap(Extension):
|
||||
def __init__(self):
|
||||
self._mod_tap_timer = None
|
||||
make_argumented_key(
|
||||
validator=mod_tap_validator,
|
||||
names=('MT',),
|
||||
on_press=self.mt_pressed,
|
||||
on_release=self.mt_released,
|
||||
)
|
||||
|
||||
def on_runtime_enable(self, keyboard):
|
||||
return
|
||||
|
||||
def on_runtime_disable(self, keyboard):
|
||||
return
|
||||
|
||||
def during_bootup(self, keyboard):
|
||||
return
|
||||
|
||||
def before_matrix_scan(self, keyboard):
|
||||
return
|
||||
|
||||
def after_matrix_scan(self, keyboard, matrix_update):
|
||||
return
|
||||
|
||||
def before_hid_send(self, keyboard):
|
||||
return
|
||||
|
||||
def after_hid_send(self, keyboard):
|
||||
return
|
||||
|
||||
def mt_pressed(self, key, state, *args, **kwargs):
|
||||
'''Sets the timer start and acts like a modifier otherwise'''
|
||||
state.keys_pressed.add(key.meta.mods)
|
||||
|
||||
self._mod_tap_timer = accurate_ticks()
|
||||
return state
|
||||
|
||||
def mt_released(self, key, state, *args, **kwargs):
|
||||
''' On keyup, check timer, and press key if needed.'''
|
||||
state.keys_pressed.discard(key.meta.mods)
|
||||
if self._mod_tap_timer and (
|
||||
accurate_ticks_diff(accurate_ticks(), self._mod_tap_timer, state.tap_time)
|
||||
):
|
||||
state.hid_pending = True
|
||||
state.tap_key(key.meta.kc)
|
||||
|
||||
self._mod_tap_timer = None
|
||||
return state
|
@@ -1,93 +1,144 @@
|
||||
import board
|
||||
import digitalio
|
||||
|
||||
from kmk.extensions import Extension
|
||||
from kmk.handlers.stock import passthrough as handler_passthrough
|
||||
from kmk.keys import make_key
|
||||
from kmk.kmktime import sleep_ms, ticks_diff, ticks_ms
|
||||
|
||||
|
||||
class Power(Extension):
|
||||
def __init__(self, powersave_pin=None, enable=False, is_target=True):
|
||||
self.enable = enable
|
||||
self.powersave_pin = powersave_pin
|
||||
self.powersave_pin = powersave_pin # Powersave pin board object
|
||||
self.is_target = is_target
|
||||
self._powersave_start = ticks_ms()
|
||||
self._usb_last_scan = ticks_ms() - 5000
|
||||
self._psp = None
|
||||
self._psp = None # Powersave pin object
|
||||
self._i2c = None
|
||||
|
||||
make_key(
|
||||
names=('PS_TOG',), on_press=self._ps_tog, on_release=handler_passthrough
|
||||
)
|
||||
make_key(
|
||||
names=('PS_ENB',), on_press=self._ps_enable, on_release=handler_passthrough
|
||||
)
|
||||
make_key(
|
||||
names=('PS_DIS',), on_press=self._ps_disable, on_release=handler_passthrough
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
return f'Power({self._to_dict()})'
|
||||
|
||||
def _to_dict(self):
|
||||
return f'Power( enable={self.enable} powersave_pin={self.powersave_pin} is_target={self.is_target} _powersave_start={self._powersave_start} _usb_last_scan={self._usb_last_scan} _psp={self._psp} )'
|
||||
return f'''Power(
|
||||
enable={self.enable}
|
||||
powersave_pin={self.powersave_pin}
|
||||
is_target={self.is_target}
|
||||
_powersave_start={self._powersave_start}
|
||||
_usb_last_scan={self._usb_last_scan}
|
||||
_psp={self._psp} )
|
||||
'''
|
||||
|
||||
def on_runtime_enable(self, keyboard):
|
||||
return
|
||||
|
||||
def on_runtime_disable(self, keyboard):
|
||||
self.disable_powersave
|
||||
|
||||
def during_bootup(self, keyboard):
|
||||
self._detect_i2c()
|
||||
self.enable = not bool(self.usb_scan)
|
||||
|
||||
def before_matrix_scan(self, keyboard_state):
|
||||
def before_matrix_scan(self, keyboard):
|
||||
if self.usb_rescan_timer():
|
||||
self.enable = not bool(self.usb_scan)
|
||||
|
||||
def after_matrix_scan(self, keyboard_state, matrix_update):
|
||||
def after_matrix_scan(self, keyboard, matrix_update):
|
||||
if matrix_update:
|
||||
self.psave_time_reset()
|
||||
else:
|
||||
self.psleep()
|
||||
|
||||
def before_hid_send(self, keyboard):
|
||||
return
|
||||
|
||||
def after_hid_send(self, keyboard):
|
||||
return
|
||||
|
||||
def enable_powersave(self):
|
||||
'''Enables power saving features'''
|
||||
print('Psave True')
|
||||
if self.powersave_pin:
|
||||
import digitalio
|
||||
|
||||
# Allows power save to prevent RGB drain.
|
||||
# Example here https://docs.nicekeyboards.com/#/nice!nano/pinout_schematic
|
||||
|
||||
if not self._psp:
|
||||
self._psp = digitalio.DigitalInOut(self.powersave_pin)
|
||||
self._psp.direction = digitalio.Direction.OUTPUT
|
||||
self._psp.value = True
|
||||
# TODO Allow a hook to stop RGB/OLED to deinit or this causes a lockup
|
||||
|
||||
self.enable = True
|
||||
|
||||
return self
|
||||
|
||||
def disable_powersave(self):
|
||||
'''Disables power saving features'''
|
||||
print('Psave False')
|
||||
if self.powersave_pin:
|
||||
import digitalio
|
||||
|
||||
# Allows power save to prevent RGB drain.
|
||||
# Example here https://docs.nicekeyboards.com/#/nice!nano/pinout_schematic
|
||||
|
||||
if not self._psp:
|
||||
self._psp = digitalio.DigitalInOut(self.powersave_pin)
|
||||
self._psp.direction = digitalio.Direction.OUTPUT
|
||||
self._psp.value = False
|
||||
# TODO Allow a hook to stop RGB/OLED to reinit
|
||||
|
||||
self.enable = False
|
||||
|
||||
return self
|
||||
|
||||
def psleep(self):
|
||||
'''
|
||||
Sleeps longer and longer to save power the more time in between updates.
|
||||
'''
|
||||
if ticks_diff(ticks_ms(), self.powersave_start) <= 20000 and self.is_target:
|
||||
if ticks_diff(ticks_ms(), self._powersave_start) <= 20000 and self.is_target:
|
||||
sleep_ms(1)
|
||||
elif ticks_diff(ticks_ms(), self.powersave_start) <= 40000 and self.is_target:
|
||||
elif ticks_diff(ticks_ms(), self._powersave_start) <= 40000 and self.is_target:
|
||||
sleep_ms(4)
|
||||
elif ticks_diff(ticks_ms(), self.powersave_start) <= 60000 and self.is_target:
|
||||
elif ticks_diff(ticks_ms(), self._powersave_start) <= 60000 and self.is_target:
|
||||
sleep_ms(8)
|
||||
elif ticks_diff(ticks_ms(), self.powersave_start) >= 240000:
|
||||
elif ticks_diff(ticks_ms(), self._powersave_start) >= 240000:
|
||||
sleep_ms(250)
|
||||
|
||||
def psave_time_reset(self):
|
||||
self.powersave_start = ticks_ms()
|
||||
return self
|
||||
self._powersave_start = ticks_ms()
|
||||
|
||||
def usb_rescan_timer(self):
|
||||
return bool(ticks_diff(ticks_ms(), self.usb_last_scan) > 5000)
|
||||
return bool(ticks_diff(ticks_ms(), self._usb_last_scan) > 5000)
|
||||
|
||||
def usb_time_reset(self):
|
||||
self.usb_last_scan = ticks_ms()
|
||||
return self
|
||||
self._usb_last_scan = ticks_ms()
|
||||
|
||||
def usb_scan(self):
|
||||
# TODO Add USB detection here. Currently lies that it's connected
|
||||
# https://github.com/adafruit/circuitpython/pull/3513
|
||||
return True
|
||||
|
||||
def _detect_i2c(self):
|
||||
'''Detects i2c devices and disables cutting power to them'''
|
||||
# TODO Figure out how this could deinit/reinit instead.
|
||||
self._i2c = board.I2C()
|
||||
devices = self._i2c.scan()
|
||||
if devices != []:
|
||||
self.powersave_pin = None
|
||||
|
||||
def _ps_tog(self):
|
||||
if self.enable:
|
||||
self.enable_powersave()
|
||||
else:
|
||||
self.disable_powersave()
|
||||
|
||||
def _ps_enable(self):
|
||||
if not self.enable:
|
||||
self.enable_powersave()
|
||||
|
||||
def _ps_disable(self):
|
||||
if self.enable:
|
||||
self.disable_powersave()
|
||||
|
@@ -141,6 +141,24 @@ class RGB(Extension):
|
||||
on_release=handler_passthrough,
|
||||
)
|
||||
|
||||
def on_runtime_enable(self, keyboard):
|
||||
return
|
||||
|
||||
def on_runtime_disable(self, keyboard):
|
||||
return
|
||||
|
||||
def during_bootup(self, keyboard):
|
||||
return
|
||||
|
||||
def before_matrix_scan(self, keyboard):
|
||||
return
|
||||
|
||||
def after_matrix_scan(self, keyboard, matrix_update):
|
||||
return
|
||||
|
||||
def before_hid_send(self, keyboard):
|
||||
return
|
||||
|
||||
def after_hid_send(self, keyboard):
|
||||
if self.animation_mode:
|
||||
self.loopcounter += 1
|
||||
@@ -150,7 +168,8 @@ class RGB(Extension):
|
||||
|
||||
return keyboard
|
||||
|
||||
def time_ms(self):
|
||||
@staticmethod
|
||||
def time_ms():
|
||||
return int(time.monotonic() * 1000)
|
||||
|
||||
def hsv_to_rgb(self, hue, sat, val):
|
||||
@@ -230,8 +249,6 @@ class RGB(Extension):
|
||||
else:
|
||||
self.set_rgb(self.hsv_to_rgb(hue, sat, val), index)
|
||||
|
||||
return self
|
||||
|
||||
def set_hsv_fill(self, hue, sat, val):
|
||||
'''
|
||||
Takes HSV values and displays it on all LEDs/Neopixels
|
||||
@@ -244,7 +261,6 @@ class RGB(Extension):
|
||||
self.set_rgb_fill(self.hsv_to_rgbw(hue, sat, val))
|
||||
else:
|
||||
self.set_rgb_fill(self.hsv_to_rgb(hue, sat, val))
|
||||
return self
|
||||
|
||||
def set_rgb(self, rgb, index):
|
||||
'''
|
||||
@@ -257,8 +273,6 @@ class RGB(Extension):
|
||||
if not self.disable_auto_write:
|
||||
self.neopixel.show()
|
||||
|
||||
return self
|
||||
|
||||
def set_rgb_fill(self, rgb):
|
||||
'''
|
||||
Takes an RGB or RGBW and displays it on all LEDs/Neopixels
|
||||
@@ -269,8 +283,6 @@ class RGB(Extension):
|
||||
if not self.disable_auto_write:
|
||||
self.neopixel.show()
|
||||
|
||||
return self
|
||||
|
||||
def increase_hue(self, step=None):
|
||||
'''
|
||||
Increases hue by step amount rolling at 360 and returning to 0
|
||||
@@ -284,8 +296,6 @@ class RGB(Extension):
|
||||
if self._check_update():
|
||||
self._do_update()
|
||||
|
||||
return self
|
||||
|
||||
def decrease_hue(self, step=None):
|
||||
'''
|
||||
Decreases hue by step amount rolling at 0 and returning to 360
|
||||
@@ -302,8 +312,6 @@ class RGB(Extension):
|
||||
if self._check_update():
|
||||
self._do_update()
|
||||
|
||||
return self
|
||||
|
||||
def increase_sat(self, step=None):
|
||||
'''
|
||||
Increases saturation by step amount stopping at 100
|
||||
@@ -320,8 +328,6 @@ class RGB(Extension):
|
||||
if self._check_update():
|
||||
self._do_update()
|
||||
|
||||
return self
|
||||
|
||||
def decrease_sat(self, step=None):
|
||||
'''
|
||||
Decreases saturation by step amount stopping at 0
|
||||
@@ -338,8 +344,6 @@ class RGB(Extension):
|
||||
if self._check_update():
|
||||
self._do_update()
|
||||
|
||||
return self
|
||||
|
||||
def increase_val(self, step=None):
|
||||
'''
|
||||
Increases value by step amount stopping at 100
|
||||
@@ -355,8 +359,6 @@ class RGB(Extension):
|
||||
if self._check_update():
|
||||
self._do_update()
|
||||
|
||||
return self
|
||||
|
||||
def decrease_val(self, step=None):
|
||||
'''
|
||||
Decreases value by step amount stopping at 0
|
||||
@@ -372,8 +374,6 @@ class RGB(Extension):
|
||||
if self._check_update():
|
||||
self._do_update()
|
||||
|
||||
return self
|
||||
|
||||
def increase_ani(self):
|
||||
'''
|
||||
Increases animation speed by 1 amount stopping at 10
|
||||
@@ -386,8 +386,6 @@ class RGB(Extension):
|
||||
if self._check_update():
|
||||
self._do_update()
|
||||
|
||||
return self
|
||||
|
||||
def decrease_ani(self):
|
||||
'''
|
||||
Decreases animation speed by 1 amount stopping at 0
|
||||
@@ -400,8 +398,6 @@ class RGB(Extension):
|
||||
if self._check_update():
|
||||
self._do_update()
|
||||
|
||||
return self
|
||||
|
||||
def off(self):
|
||||
'''
|
||||
Turns off all LEDs/Neopixels without changing stored values
|
||||
@@ -409,8 +405,6 @@ class RGB(Extension):
|
||||
if self.neopixel:
|
||||
self.set_hsv_fill(0, 0, 0)
|
||||
|
||||
return self
|
||||
|
||||
def show(self):
|
||||
'''
|
||||
Turns on all LEDs/Neopixels without changing stored values
|
||||
@@ -418,8 +412,6 @@ class RGB(Extension):
|
||||
if self.neopixel:
|
||||
self.neopixel.show()
|
||||
|
||||
return self
|
||||
|
||||
def animate(self):
|
||||
'''
|
||||
Activates a "step" in the animation based on the active mode
|
||||
@@ -448,8 +440,6 @@ class RGB(Extension):
|
||||
else:
|
||||
self.off()
|
||||
|
||||
return self
|
||||
|
||||
def _animation_step(self):
|
||||
interval = self.time_ms() - self.time
|
||||
if interval >= max(self.intervals):
|
||||
@@ -471,7 +461,6 @@ class RGB(Extension):
|
||||
self.pos = 0
|
||||
self.reverse_animation = False
|
||||
self.effect_init = False
|
||||
return self
|
||||
|
||||
def _check_update(self):
|
||||
return bool(self.animation_mode == AnimationModes.STATIC_STANDBY)
|
||||
@@ -483,7 +472,6 @@ class RGB(Extension):
|
||||
def effect_static(self):
|
||||
self.set_hsv_fill(self.hue, self.sat, self.val)
|
||||
self.animation_mode = AnimationModes.STATIC_STANDBY
|
||||
return self
|
||||
|
||||
def effect_breathing(self):
|
||||
# http://sean.voisen.org/blog/2011/10/breathing-led-with-arduino/
|
||||
@@ -496,20 +484,14 @@ class RGB(Extension):
|
||||
self.pos = (self.pos + self.animation_speed) % 256
|
||||
self.set_hsv_fill(self.hue, self.sat, self.val)
|
||||
|
||||
return self
|
||||
|
||||
def effect_breathing_rainbow(self):
|
||||
self.increase_hue(self.animation_speed)
|
||||
self.effect_breathing()
|
||||
|
||||
return self
|
||||
|
||||
def effect_rainbow(self):
|
||||
self.increase_hue(self.animation_speed)
|
||||
self.set_hsv_fill(self.hue, self.sat, self.val)
|
||||
|
||||
return self
|
||||
|
||||
def effect_swirl(self):
|
||||
self.increase_hue(self.animation_speed)
|
||||
self.disable_auto_write = True # Turn off instantly showing
|
||||
@@ -521,7 +503,6 @@ class RGB(Extension):
|
||||
# Show final results
|
||||
self.disable_auto_write = False # Resume showing changes
|
||||
self.show()
|
||||
return self
|
||||
|
||||
def effect_knight(self):
|
||||
# Determine which LEDs should be lit up
|
||||
@@ -546,8 +527,6 @@ class RGB(Extension):
|
||||
self.disable_auto_write = False # Resume showing changes
|
||||
self.show()
|
||||
|
||||
return self
|
||||
|
||||
def _rgb_tog(self, key, state, *args, **kwargs):
|
||||
if self.animation_mode == AnimationModes.STATIC:
|
||||
self.animation_mode = AnimationModes.STATIC_STANDBY
|
||||
@@ -556,69 +535,54 @@ class RGB(Extension):
|
||||
self.animation_mode = AnimationModes.STATIC
|
||||
self._do_update()
|
||||
self.enable = not self.enable
|
||||
return state
|
||||
|
||||
def _rgb_hui(self, key, state, *args, **kwargs):
|
||||
self.increase_hue()
|
||||
return state
|
||||
|
||||
def _rgb_hud(self, key, state, *args, **kwargs):
|
||||
self.decrease_hue()
|
||||
return state
|
||||
|
||||
def _rgb_sai(self, key, state, *args, **kwargs):
|
||||
self.increase_sat()
|
||||
return state
|
||||
|
||||
def _rgb_sad(self, key, state, *args, **kwargs):
|
||||
self.decrease_sat()
|
||||
return state
|
||||
|
||||
def _rgb_vai(self, key, state, *args, **kwargs):
|
||||
self.increase_val()
|
||||
return state
|
||||
|
||||
def _rgb_vad(self, key, state, *args, **kwargs):
|
||||
self.decrease_val()
|
||||
return state
|
||||
|
||||
def _rgb_ani(self, key, state, *args, **kwargs):
|
||||
self.increase_ani()
|
||||
return state
|
||||
|
||||
def _rgb_and(self, key, state, *args, **kwargs):
|
||||
self.decrease_ani()
|
||||
return state
|
||||
|
||||
def _rgb_mode_static(self, key, state, *args, **kwargs):
|
||||
self.effect_init = True
|
||||
self.animation_mode = AnimationModes.STATIC
|
||||
return state
|
||||
|
||||
def _rgb_mode_breathe(self, key, state, *args, **kwargs):
|
||||
self.effect_init = True
|
||||
self.animation_mode = AnimationModes.BREATHING
|
||||
return state
|
||||
|
||||
def _rgb_mode_breathe_rainbow(self, key, state, *args, **kwargs):
|
||||
self.effect_init = True
|
||||
self.animation_mode = AnimationModes.BREATHING_RAINBOW
|
||||
return state
|
||||
|
||||
def _rgb_mode_rainbow(self, key, state, *args, **kwargs):
|
||||
self.effect_init = True
|
||||
self.animation_mode = AnimationModes.RAINBOW
|
||||
return state
|
||||
|
||||
def _rgb_mode_swirl(self, key, state, *args, **kwargs):
|
||||
self.effect_init = True
|
||||
self.animation_mode = AnimationModes.SWIRL
|
||||
return state
|
||||
|
||||
def _rgb_mode_knight(self, key, state, *args, **kwargs):
|
||||
self.effect_init = True
|
||||
self.animation_mode = AnimationModes.KNIGHT
|
||||
return state
|
||||
|
||||
def _rgb_reset(self, key, state, *args, **kwargs):
|
||||
self.hue = self.hue_default
|
||||
@@ -627,4 +591,3 @@ class RGB(Extension):
|
||||
if self.animation_mode == AnimationModes.STATIC_STANDBY:
|
||||
self.animation_mode = AnimationModes.STATIC
|
||||
self._do_update()
|
||||
return state
|
||||
|
@@ -37,6 +37,12 @@ class Split(Extension):
|
||||
self.uart_pin = uart_pin
|
||||
self.uart_timeout = uart_timeout
|
||||
|
||||
def on_runtime_enable(self, keyboard):
|
||||
return
|
||||
|
||||
def on_runtime_disable(self, keyboard):
|
||||
return
|
||||
|
||||
def during_bootup(self, keyboard):
|
||||
try:
|
||||
# Working around https://github.com/adafruit/circuitpython/issues/1769
|
||||
@@ -75,14 +81,21 @@ class Split(Extension):
|
||||
for cidx in range(cols_to_calc):
|
||||
keyboard.coord_mapping.append(intify_coordinate(ridx, cidx))
|
||||
|
||||
def before_matrix_scan(self, keyboard_state):
|
||||
def before_matrix_scan(self, keyboard):
|
||||
if self._is_target:
|
||||
return self._receive()
|
||||
return None
|
||||
|
||||
def after_matrix_scan(self, keyboard_state, matrix_update):
|
||||
def after_matrix_scan(self, keyboard, matrix_update):
|
||||
if matrix_update is not None and not self._is_target:
|
||||
self._send(matrix_update)
|
||||
|
||||
def before_hid_send(self, keyboard):
|
||||
return
|
||||
|
||||
def after_hid_send(self, keyboard):
|
||||
return
|
||||
|
||||
def _send(self, update):
|
||||
if self.split_target_left:
|
||||
update[1] += self.split_offset
|
||||
|
Reference in New Issue
Block a user