Move all remaining state into the single store, woot!
This commit is contained in:
parent
b9dfffd2b3
commit
ffd47c478f
@ -2,17 +2,32 @@ from micropython import const
|
|||||||
|
|
||||||
KEY_UP_EVENT = const(1)
|
KEY_UP_EVENT = const(1)
|
||||||
KEY_DOWN_EVENT = const(2)
|
KEY_DOWN_EVENT = const(2)
|
||||||
|
INIT_FIRMWARE_EVENT = const(3)
|
||||||
|
|
||||||
|
|
||||||
def key_up_event(keycode):
|
def init_firmware(keymap, row_pins, col_pins, diode_orientation):
|
||||||
|
return {
|
||||||
|
'type': INIT_FIRMWARE_EVENT,
|
||||||
|
'keymap': keymap,
|
||||||
|
'row_pins': row_pins,
|
||||||
|
'col_pins': col_pins,
|
||||||
|
'diode_orientation': diode_orientation,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def key_up_event(keycode, row, col):
|
||||||
return {
|
return {
|
||||||
'type': KEY_UP_EVENT,
|
'type': KEY_UP_EVENT,
|
||||||
'keycode': keycode,
|
'keycode': keycode,
|
||||||
|
'row': row,
|
||||||
|
'col': col,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def key_down_event(keycode):
|
def key_down_event(keycode, row, col):
|
||||||
return {
|
return {
|
||||||
'type': KEY_DOWN_EVENT,
|
'type': KEY_DOWN_EVENT,
|
||||||
'keycode': keycode,
|
'keycode': keycode,
|
||||||
|
'row': row,
|
||||||
|
'col': col,
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
import logging
|
import logging
|
||||||
|
import sys
|
||||||
|
|
||||||
from kmk.common.event_defs import KEY_DOWN_EVENT, KEY_UP_EVENT
|
from kmk.common.consts import DiodeOrientation
|
||||||
|
from kmk.common.event_defs import (INIT_FIRMWARE_EVENT, KEY_DOWN_EVENT,
|
||||||
|
KEY_UP_EVENT)
|
||||||
|
|
||||||
|
|
||||||
class ReduxStore:
|
class ReduxStore:
|
||||||
@ -9,38 +12,69 @@ class ReduxStore:
|
|||||||
self.logger = logging.getLogger(__name__)
|
self.logger = logging.getLogger(__name__)
|
||||||
self.logger.setLevel(log_level)
|
self.logger.setLevel(log_level)
|
||||||
self.state = self.reducer(logger=self.logger)
|
self.state = self.reducer(logger=self.logger)
|
||||||
|
self.callbacks = []
|
||||||
|
|
||||||
def dispatch(self, action):
|
def dispatch(self, action):
|
||||||
self.logger.debug('Dispatching action: {}'.format(action))
|
self.logger.debug('Dispatching action: {}'.format(action))
|
||||||
self.state = self.reducer(self.state, action)
|
self.state = self.reducer(self.state, action)
|
||||||
self.logger.debug('Dispatching complete: {}'.format(action))
|
self.logger.debug('Dispatching complete: {}'.format(action))
|
||||||
|
|
||||||
|
self.logger.debug('Calling subscriptions')
|
||||||
|
|
||||||
|
for cb in self.callbacks:
|
||||||
|
if cb is not None:
|
||||||
|
try:
|
||||||
|
cb(self.state, action)
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.error('Callback failed, moving on')
|
||||||
|
print(sys.print_exception(e), file=sys.stderr)
|
||||||
|
|
||||||
|
self.logger.debug('Callbacks complete')
|
||||||
|
|
||||||
def get_state(self):
|
def get_state(self):
|
||||||
return self.state
|
return self.state
|
||||||
|
|
||||||
|
def subscribe(self, callback):
|
||||||
|
self.callbacks.append(callback)
|
||||||
|
return len(self.callbacks) - 1
|
||||||
|
|
||||||
|
def unsubscribe(self, idx):
|
||||||
|
self.callbacks[idx] = None
|
||||||
|
|
||||||
|
|
||||||
class InternalState:
|
class InternalState:
|
||||||
modifiers_pressed = frozenset()
|
modifiers_pressed = frozenset()
|
||||||
keys_pressed = frozenset()
|
keys_pressed = frozenset()
|
||||||
|
keymap = []
|
||||||
|
row_pins = []
|
||||||
|
col_pins = []
|
||||||
|
matrix = []
|
||||||
|
diode_orientation = DiodeOrientation.COLUMNS
|
||||||
|
|
||||||
|
@property
|
||||||
|
def __dict__(self):
|
||||||
|
return {
|
||||||
|
'keys_pressed': self.keys_pressed,
|
||||||
|
'modifiers_pressed': self.modifiers_pressed,
|
||||||
|
'keymap': self.keymap,
|
||||||
|
'col_pins': self.col_pins,
|
||||||
|
'row_pins': self.row_pins,
|
||||||
|
'diode_orientation': self.diode_orientation,
|
||||||
|
}
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return 'InternalState(mods={}, keys={})'.format(
|
return 'InternalState({})'.format(self.__dict__)
|
||||||
self.modifiers_pressed,
|
|
||||||
self.keys_pressed,
|
|
||||||
)
|
|
||||||
|
|
||||||
def copy(self, modifiers_pressed=None, keys_pressed=None):
|
def copy(self, **kwargs):
|
||||||
new_state = InternalState()
|
new_state = InternalState()
|
||||||
|
|
||||||
if modifiers_pressed is None:
|
for k, v in self.__dict__.items():
|
||||||
new_state.modifiers_pressed = self.modifiers_pressed.copy()
|
if hasattr(new_state, k):
|
||||||
else:
|
setattr(new_state, k, v)
|
||||||
new_state.modifiers_pressed = modifiers_pressed
|
|
||||||
|
|
||||||
if keys_pressed is None:
|
for k, v in kwargs.items():
|
||||||
new_state.keys_pressed = self.keys_pressed.copy()
|
if hasattr(new_state, k):
|
||||||
else:
|
setattr(new_state, k, v)
|
||||||
new_state.keys_pressed = keys_pressed
|
|
||||||
|
|
||||||
return new_state
|
return new_state
|
||||||
|
|
||||||
@ -59,11 +93,41 @@ def kmk_reducer(state=None, action=None, logger=None):
|
|||||||
return state
|
return state
|
||||||
|
|
||||||
if action['type'] == KEY_UP_EVENT:
|
if action['type'] == KEY_UP_EVENT:
|
||||||
return state.copy(keys_pressed=frozenset(
|
return state.copy(
|
||||||
key for key in state.keys_pressed if key != action['keycode']
|
keys_pressed=frozenset(
|
||||||
))
|
key for key in state.keys_pressed if key != action['keycode']
|
||||||
|
),
|
||||||
|
matrix=[
|
||||||
|
r if ridx != action['row'] else [
|
||||||
|
c if cidx != action['col'] else False
|
||||||
|
for cidx, c in enumerate(r)
|
||||||
|
]
|
||||||
|
for ridx, r in enumerate(state.matrix)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
if action['type'] == KEY_DOWN_EVENT:
|
if action['type'] == KEY_DOWN_EVENT:
|
||||||
return state.copy(keys_pressed=(
|
return state.copy(
|
||||||
state.keys_pressed | {action['keycode']}
|
keys_pressed=(
|
||||||
))
|
state.keys_pressed | {action['keycode']}
|
||||||
|
),
|
||||||
|
matrix=[
|
||||||
|
r if ridx != action['row'] else [
|
||||||
|
c if cidx != action['col'] else True
|
||||||
|
for cidx, c in enumerate(r)
|
||||||
|
]
|
||||||
|
for ridx, r in enumerate(state.matrix)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
if action['type'] == INIT_FIRMWARE_EVENT:
|
||||||
|
return state.copy(
|
||||||
|
keymap=action['keymap'],
|
||||||
|
row_pins=action['row_pins'],
|
||||||
|
col_pins=action['col_pins'],
|
||||||
|
diode_orientation=action['diode_orientation'],
|
||||||
|
matrix=[
|
||||||
|
[False for c in action['col_pins']]
|
||||||
|
for r in action['row_pins']
|
||||||
|
],
|
||||||
|
)
|
||||||
|
@ -4,18 +4,22 @@ from kmk.common.event_defs import key_down_event, key_up_event
|
|||||||
class Keymap:
|
class Keymap:
|
||||||
def __init__(self, map):
|
def __init__(self, map):
|
||||||
self.map = map
|
self.map = map
|
||||||
self.state = [
|
|
||||||
[False for _ in row]
|
|
||||||
for row in self.map
|
|
||||||
]
|
|
||||||
|
|
||||||
def parse(self, matrix, store):
|
def parse(self, matrix, store):
|
||||||
|
state = store.get_state()
|
||||||
|
|
||||||
for ridx, row in enumerate(matrix):
|
for ridx, row in enumerate(matrix):
|
||||||
for cidx, col in enumerate(row):
|
for cidx, col in enumerate(row):
|
||||||
if col != self.state[ridx][cidx]:
|
if col != state.matrix[ridx][cidx]:
|
||||||
if col:
|
if col:
|
||||||
store.dispatch(key_down_event(self.map[ridx][cidx]))
|
store.dispatch(key_down_event(
|
||||||
|
row=ridx,
|
||||||
|
col=cidx,
|
||||||
|
keycode=self.map[ridx][cidx],
|
||||||
|
))
|
||||||
else:
|
else:
|
||||||
store.dispatch(key_up_event(self.map[ridx][cidx]))
|
store.dispatch(key_up_event(
|
||||||
|
row=ridx,
|
||||||
self.state = matrix
|
col=cidx,
|
||||||
|
keycode=self.map[ridx][cidx],
|
||||||
|
))
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
from kmk.common.event_defs import init_firmware
|
||||||
from kmk.common.internal_state import ReduxStore, kmk_reducer
|
from kmk.common.internal_state import ReduxStore, kmk_reducer
|
||||||
from kmk.common.keymap import Keymap
|
from kmk.common.keymap import Keymap
|
||||||
|
|
||||||
@ -14,10 +15,31 @@ class Firmware:
|
|||||||
self, keymap, row_pins, col_pins, diode_orientation,
|
self, keymap, row_pins, col_pins, diode_orientation,
|
||||||
log_level=logging.NOTSET,
|
log_level=logging.NOTSET,
|
||||||
):
|
):
|
||||||
self.raw_keymap = keymap
|
self.cached_state = None
|
||||||
self.keymap = Keymap(keymap)
|
|
||||||
self.matrix = MatrixScanner(col_pins, row_pins, diode_orientation)
|
|
||||||
self.store = ReduxStore(kmk_reducer, log_level=log_level)
|
self.store = ReduxStore(kmk_reducer, log_level=log_level)
|
||||||
|
self.store.subscribe(
|
||||||
|
lambda state, action: self._subscription(state, action),
|
||||||
|
)
|
||||||
|
self.store.dispatch(init_firmware(
|
||||||
|
keymap=keymap,
|
||||||
|
row_pins=row_pins,
|
||||||
|
col_pins=col_pins,
|
||||||
|
diode_orientation=diode_orientation,
|
||||||
|
))
|
||||||
|
|
||||||
|
def _subscription(self, state, action):
|
||||||
|
if self.cached_state is None or self.cached_state.keymap != state.keymap:
|
||||||
|
self.keymap = Keymap(state.keymap)
|
||||||
|
|
||||||
|
if self.cached_state is None or any(
|
||||||
|
getattr(self.cached_state, k) != getattr(state, k)
|
||||||
|
for k in state.__dict__.keys()
|
||||||
|
):
|
||||||
|
self.matrix = MatrixScanner(
|
||||||
|
state.col_pins,
|
||||||
|
state.row_pins,
|
||||||
|
state.diode_orientation,
|
||||||
|
)
|
||||||
|
|
||||||
def go(self):
|
def go(self):
|
||||||
while True:
|
while True:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user