Move all remaining state into the single store, woot!

This commit is contained in:
Josh Klar 2018-09-03 15:21:34 -07:00
parent b9dfffd2b3
commit ffd47c478f
4 changed files with 139 additions and 34 deletions

View File

@ -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,
} }

View File

@ -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']
],
)

View File

@ -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],
))

View File

@ -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: