Support a special form of macro based on rotary encoder directions
This commit is contained in:
parent
e2c9567bbf
commit
6589982eda
76
kmk/common/macros/rotary_encoder.py
Normal file
76
kmk/common/macros/rotary_encoder.py
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
import math
|
||||||
|
|
||||||
|
from kmk.common.event_defs import (hid_report_event, keycode_down_event,
|
||||||
|
keycode_up_event)
|
||||||
|
from kmk.common.keycodes import Media
|
||||||
|
from kmk.common.rotary_encoder import RotaryEncoder
|
||||||
|
|
||||||
|
VAL_FALSE = False + 1
|
||||||
|
VAL_NONE = True + 2
|
||||||
|
VAL_TRUE = True + 1
|
||||||
|
VOL_UP_PRESS = keycode_down_event(Media.KC_AUDIO_VOL_UP)
|
||||||
|
VOL_UP_RELEASE = keycode_up_event(Media.KC_AUDIO_VOL_UP)
|
||||||
|
VOL_DOWN_PRESS = keycode_down_event(Media.KC_AUDIO_VOL_DOWN)
|
||||||
|
VOL_DOWN_RELEASE = keycode_up_event(Media.KC_AUDIO_VOL_DOWN)
|
||||||
|
|
||||||
|
|
||||||
|
class RotaryEncoderMacro:
|
||||||
|
def __init__(self, pos_pin, neg_pin, slop_history=24, slop_threshold=0.7):
|
||||||
|
self.encoder = RotaryEncoder(pos_pin, neg_pin)
|
||||||
|
self.max_history = slop_history
|
||||||
|
self.history = bytearray(slop_history)
|
||||||
|
self.history_idx = 0
|
||||||
|
self.history_threshold = math.floor(slop_threshold * slop_history)
|
||||||
|
|
||||||
|
def scan(self):
|
||||||
|
# Anti-slop logic
|
||||||
|
self.history[self.history_idx] = 0
|
||||||
|
|
||||||
|
reading = self.encoder.direction()
|
||||||
|
self.history[self.history_idx] = VAL_NONE if reading is None else reading + 1
|
||||||
|
|
||||||
|
self.history_idx += 1
|
||||||
|
|
||||||
|
if self.history_idx >= self.max_history:
|
||||||
|
self.history_idx = 0
|
||||||
|
|
||||||
|
nones = 0
|
||||||
|
trues = 0
|
||||||
|
falses = 0
|
||||||
|
|
||||||
|
for val in self.history:
|
||||||
|
if val == VAL_NONE:
|
||||||
|
nones += 1
|
||||||
|
elif val == VAL_TRUE:
|
||||||
|
trues += 1
|
||||||
|
elif val == VAL_FALSE:
|
||||||
|
falses += 1
|
||||||
|
|
||||||
|
if nones >= self.history_threshold:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if trues >= self.history_threshold:
|
||||||
|
return self.on_increase()
|
||||||
|
|
||||||
|
if falses >= self.history_threshold:
|
||||||
|
return self.on_decrease()
|
||||||
|
|
||||||
|
def on_decrease(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def on_increase(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class VolumeRotaryEncoder(RotaryEncoderMacro):
|
||||||
|
def on_decrease(self):
|
||||||
|
yield VOL_DOWN_PRESS
|
||||||
|
yield hid_report_event
|
||||||
|
yield VOL_DOWN_RELEASE
|
||||||
|
yield hid_report_event
|
||||||
|
|
||||||
|
def on_increase(self):
|
||||||
|
yield VOL_UP_PRESS
|
||||||
|
yield hid_report_event
|
||||||
|
yield VOL_UP_RELEASE
|
||||||
|
yield hid_report_event
|
@ -19,6 +19,9 @@ class Firmware:
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
logger.setLevel(log_level)
|
logger.setLevel(log_level)
|
||||||
|
|
||||||
|
import kmk_keyboard_user
|
||||||
|
self.encoders = getattr(kmk_keyboard_user, 'encoders', [])
|
||||||
|
|
||||||
self.hydrated = False
|
self.hydrated = False
|
||||||
|
|
||||||
self.store = Store(kmk_reducer, log_level=log_level)
|
self.store = Store(kmk_reducer, log_level=log_level)
|
||||||
@ -58,3 +61,10 @@ class Firmware:
|
|||||||
|
|
||||||
if update:
|
if update:
|
||||||
self.store.dispatch(update)
|
self.store.dispatch(update)
|
||||||
|
|
||||||
|
for encoder in self.encoders:
|
||||||
|
eupdate = encoder.scan()
|
||||||
|
|
||||||
|
if eupdate:
|
||||||
|
for event in eupdate:
|
||||||
|
self.store.dispatch(event)
|
||||||
|
@ -11,9 +11,12 @@ class Anything:
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return 'Anything<{}>'.format(self.name)
|
return 'Anything<{}>'.format(self.name)
|
||||||
|
|
||||||
|
def init(self, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def value(self):
|
def value(self):
|
||||||
return None
|
return False
|
||||||
|
|
||||||
|
|
||||||
class Passthrough:
|
class Passthrough:
|
||||||
@ -23,6 +26,10 @@ class Passthrough:
|
|||||||
|
|
||||||
class Pin:
|
class Pin:
|
||||||
board = Passthrough()
|
board = Passthrough()
|
||||||
|
IN = 'IN'
|
||||||
|
OUT = 'OUT'
|
||||||
|
PULL_DOWN = 'PULL_DOWN'
|
||||||
|
PULL_UP = 'PULL_UP'
|
||||||
|
|
||||||
def __call__(self, *args, **kwargs):
|
def __call__(self, *args, **kwargs):
|
||||||
return self.board
|
return self.board
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
from kmk.common.consts import DiodeOrientation, UnicodeModes
|
from kmk.common.consts import DiodeOrientation, UnicodeModes
|
||||||
from kmk.common.keycodes import KC
|
from kmk.common.keycodes import KC
|
||||||
|
from kmk.common.macros.rotary_encoder import VolumeRotaryEncoder
|
||||||
from kmk.common.macros.simple import send_string, simple_key_sequence
|
from kmk.common.macros.simple import send_string, simple_key_sequence
|
||||||
from kmk.common.macros.unicode import unicode_string_sequence
|
from kmk.common.macros.unicode import unicode_string_sequence
|
||||||
from kmk.common.pins import Pin as P
|
from kmk.common.pins import Pin as P
|
||||||
@ -15,6 +16,10 @@ rows = (P.D12, P.D11, P.D10)
|
|||||||
diode_orientation = DiodeOrientation.COLUMNS
|
diode_orientation = DiodeOrientation.COLUMNS
|
||||||
unicode_mode = UnicodeModes.LINUX
|
unicode_mode = UnicodeModes.LINUX
|
||||||
|
|
||||||
|
encoders = [
|
||||||
|
VolumeRotaryEncoder(P.A3, P.A2),
|
||||||
|
]
|
||||||
|
|
||||||
emoticons = AttrDict({
|
emoticons = AttrDict({
|
||||||
# Emojis
|
# Emojis
|
||||||
'BEER': r'🍺',
|
'BEER': r'🍺',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user