138 lines
3.5 KiB
Python
138 lines
3.5 KiB
Python
import logging
|
|
|
|
from micropython import const
|
|
|
|
from kmk.common.keycodes import Keycodes
|
|
|
|
KEY_UP_EVENT = const(1)
|
|
KEY_DOWN_EVENT = const(2)
|
|
INIT_FIRMWARE_EVENT = const(3)
|
|
NEW_MATRIX_EVENT = const(4)
|
|
HID_REPORT_EVENT = const(5)
|
|
KEYCODE_UP_EVENT = const(6)
|
|
KEYCODE_DOWN_EVENT = const(7)
|
|
MACRO_COMPLETE_EVENT = const(8)
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
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(row, col):
|
|
return {
|
|
'type': KEY_UP_EVENT,
|
|
'row': row,
|
|
'col': col,
|
|
}
|
|
|
|
|
|
def key_down_event(row, col):
|
|
return {
|
|
'type': KEY_DOWN_EVENT,
|
|
'row': row,
|
|
'col': col,
|
|
}
|
|
|
|
|
|
def keycode_up_event(keycode):
|
|
'''
|
|
Press a key by Keycode object, bypassing the keymap. Used mostly for
|
|
macros.
|
|
'''
|
|
return {
|
|
'type': KEYCODE_UP_EVENT,
|
|
'keycode': keycode,
|
|
}
|
|
|
|
|
|
def keycode_down_event(keycode):
|
|
'''
|
|
Release a key by Keycode object, bypassing the keymap. Used mostly for
|
|
macros.
|
|
'''
|
|
return {
|
|
'type': KEYCODE_DOWN_EVENT,
|
|
'keycode': keycode,
|
|
}
|
|
|
|
|
|
def new_matrix_event(matrix):
|
|
return {
|
|
'type': NEW_MATRIX_EVENT,
|
|
'matrix': matrix,
|
|
}
|
|
|
|
|
|
def hid_report_event():
|
|
return {
|
|
'type': HID_REPORT_EVENT,
|
|
}
|
|
|
|
|
|
def macro_complete_event(macro):
|
|
return {
|
|
'type': MACRO_COMPLETE_EVENT,
|
|
'macro': macro,
|
|
}
|
|
|
|
|
|
def matrix_changed(new_matrix):
|
|
def _key_pressed(dispatch, get_state):
|
|
state = get_state()
|
|
# Temporarily preserve a reference to the old event
|
|
# We do fake Redux around here because microcontrollers
|
|
# aren't exactly RAM or CPU powerhouses - the state does
|
|
# mutate in place. Unfortunately this makes reasoning
|
|
# about code a bit messier and really hurts one of the
|
|
# selling points of Redux. Former development versions
|
|
# of KMK created new InternalState copies every single
|
|
# time the state changed, but it was sometimes slow.
|
|
old_matrix = state.matrix
|
|
old_keys_pressed = state.keys_pressed
|
|
|
|
dispatch(new_matrix_event(new_matrix))
|
|
|
|
with get_state() as new_state:
|
|
for ridx, row in enumerate(new_state.matrix):
|
|
for cidx, col in enumerate(row):
|
|
if col != old_matrix[ridx][cidx]:
|
|
if col:
|
|
dispatch(key_down_event(
|
|
row=ridx,
|
|
col=cidx,
|
|
))
|
|
else:
|
|
dispatch(key_up_event(
|
|
row=ridx,
|
|
col=cidx,
|
|
))
|
|
|
|
with get_state() as new_state:
|
|
if old_keys_pressed != new_state.keys_pressed:
|
|
dispatch(hid_report_event())
|
|
|
|
if Keycodes.KMK.KC_RESET in new_state.keys_pressed:
|
|
try:
|
|
import machine
|
|
machine.bootloader()
|
|
except ImportError:
|
|
logger.warning('Tried to reset to bootloader, but not supported on this chip?')
|
|
|
|
while get_state().macros_pending:
|
|
macro = get_state().macros_pending[0]
|
|
|
|
for event in macro():
|
|
dispatch(event)
|
|
|
|
dispatch(macro_complete_event(macro))
|
|
|
|
return _key_pressed
|