-
Notifications
You must be signed in to change notification settings - Fork 486
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
214 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
import kmk.matrix # isort:skip | ||
|
||
# Thanks for sticking around. Now let's do real work, starting below | ||
|
||
import busio | ||
import gc | ||
|
||
from kmk.internal_state_slave import InternalState | ||
from kmk.matrix import MatrixScanner | ||
|
||
|
||
class Firmware: | ||
debug_enabled = False | ||
|
||
row_pins = None | ||
col_pins = None | ||
diode_orientation = None | ||
|
||
extra_data_pin = None | ||
split_offsets = () | ||
split_flip = False | ||
split_side = None | ||
split_type = None | ||
split_master_left = True | ||
is_master = False | ||
uart = None | ||
uart_flip = True | ||
uart_pin = None | ||
|
||
def __init__(self): | ||
self._state = InternalState(self) | ||
|
||
def _handle_matrix_report(self, update=None): | ||
''' | ||
Bulk processing of update code for each cycle | ||
:param update: | ||
''' | ||
if update is not None: | ||
self._state.matrix_changed( | ||
update[0], | ||
update[1], | ||
update[2], | ||
) | ||
|
||
def _send_to_master(self, update): | ||
if self.split_master_left: | ||
update[1] += self.split_offsets[update[0]] | ||
else: | ||
update[1] -= self.split_offsets[update[0]] | ||
if self.uart is not None: | ||
self.uart.write(update) | ||
|
||
def _send_debug(self, message): | ||
''' | ||
Prepends DEB and appends a newline to allow debug messages to | ||
be detected and handled differently than typical keypresses. | ||
:param message: Debug message | ||
''' | ||
if self.uart is not None: | ||
self.uart.write('DEB') | ||
self.uart.write(message, '\n') | ||
|
||
def init_uart(self, pin, timeout=20): | ||
return busio.UART(tx=pin, rx=None, timeout=timeout) | ||
|
||
def go(self): | ||
assert self.row_pins, 'no GPIO pins defined for matrix rows' | ||
assert self.col_pins, 'no GPIO pins defined for matrix columns' | ||
assert self.diode_orientation is not None, 'diode orientation must be defined' | ||
|
||
if self.split_flip: | ||
self.col_pins = list(reversed(self.col_pins)) | ||
|
||
# Split keyboard Init | ||
if self.split_side == "Left": | ||
self.split_master_left = True | ||
elif self.split_side == "Right": | ||
self.split_master_left = False | ||
|
||
if self.uart_pin is not None: | ||
self.uart = self.init_uart(self.uart_pin) | ||
|
||
self.matrix = MatrixScanner( | ||
cols=self.col_pins, | ||
rows=self.row_pins, | ||
diode_orientation=self.diode_orientation, | ||
rollover_cols_every_rows=getattr(self, 'rollover_cols_every_rows', None), | ||
swap_indicies=getattr(self, 'swap_indicies', None), | ||
) | ||
|
||
if self.debug_enabled: | ||
print("Firin' lazers. Keyboard is booted.") | ||
|
||
while True: | ||
state_changed = False | ||
|
||
update = self.matrix.scan_for_changes() | ||
|
||
if update is not None: | ||
# This keyboard is a slave, and needs to send data to master | ||
self._send_to_master(update) | ||
|
||
|
||
if self.debug_enabled and state_changed: | ||
print('New State: {}'.format(self._state._to_dict())) | ||
|
||
gc.collect() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
from kmk.util import intify_coordinate | ||
|
||
|
||
class InternalState: | ||
keys_pressed = set() | ||
coord_keys_pressed = {} | ||
|
||
def __init__(self, config): | ||
self.config = config | ||
|
||
def __repr__(self): | ||
return 'InternalState({})'.format(self._to_dict()) | ||
|
||
def _to_dict(self): | ||
ret = { | ||
'keys_pressed': self.keys_pressed, | ||
} | ||
|
||
return ret | ||
|
||
def _find_key_in_map(self, row, col): | ||
# Later-added layers have priority. Sift through the layers | ||
# in reverse order until we find a valid keycode object | ||
for layer in self.reversed_active_layers: | ||
layer_key = self.config.keymap[layer][row][col] | ||
|
||
if self.config.debug_enabled: | ||
print('Resolved key: {}'.format(layer_key)) | ||
|
||
return layer_key | ||
|
||
def matrix_changed(self, row, col, is_pressed): | ||
if self.config.debug_enabled: | ||
print('Matrix changed (col, row, pressed?): {}, {}, {}'.format( | ||
col, row, is_pressed, | ||
)) | ||
|
||
int_coord = intify_coordinate(row, col) | ||
kc_changed = self._find_key_in_map(row, col) | ||
|
||
if kc_changed is None: | ||
print('No key accessible for col, row: {}, {}'.format(row, col)) | ||
return self | ||
|
||
return self.process_key(kc_changed, is_pressed, int_coord, (row, col)) | ||
|
||
def process_key(self, key, is_pressed, coord_int=None, coord_raw=None): | ||
if self.tapping: | ||
self._process_tap_dance(key, is_pressed) | ||
else: | ||
if is_pressed: | ||
key._on_press(self, coord_int, coord_raw) | ||
else: | ||
key._on_release(self, coord_int, coord_raw) | ||
|
||
if self.config.leader_mode % 2 == 1: | ||
self._process_leader_mode() | ||
|
||
return self | ||
|
||
def remove_key(self, keycode): | ||
self.keys_pressed.discard(keycode) | ||
return self.process_key(keycode, False) | ||
|
||
def add_key(self, keycode): | ||
self.keys_pressed.add(keycode) | ||
return self.process_key(keycode, True) | ||
|
||
def tap_key(self, keycode): | ||
self.add_key(keycode) | ||
# On the next cycle, we'll remove the key. | ||
self.set_timeout(False, lambda: self.remove_key(keycode)) | ||
|
||
return self | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
from kmk.firmware_slave import Firmware as _Firmware | ||
|
||
|
||
class Firmware(_Firmware): | ||
hid_helper = None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import board | ||
|
||
from kmk.consts import DiodeOrientation | ||
from kmk.mcus.circuitpython_samd21 import Firmware | ||
from kmk.pins import Pin as P | ||
|
||
keyboard = Firmware() | ||
|
||
keyboard.col_pins = (P.RX, P.A1, P.A2, P.A3, P.A4, P.A5) | ||
keyboard.row_pins = (P.D13, P.D11, P.D10, P.D9, P.D7) | ||
keyboard.diode_orientation = DiodeOrientation.COLUMNS | ||
|
||
keyboard.split_type = "UART" | ||
keyboard.split_flip = True | ||
keyboard.split_offsets = [6, 6, 6, 6, 6] | ||
keyboard.uart_pin = board.SDA | ||
keyboard.extra_data_pin = board.SCL | ||
|
||
# ------------------User level config variables --------------------------------------- | ||
keyboard.debug_enabled = True | ||
|
||
# ---------------------- Keymap --------------------------------------------------------- | ||
|
||
|
||
if __name__ == '__main__': | ||
keyboard.go() |