104 lines
3.2 KiB
Python
104 lines
3.2 KiB
Python
import busio
|
|
import gc
|
|
|
|
from kmk.extensions import Extension
|
|
from kmk.kmktime import sleep_ms
|
|
from kmk.matrix import intify_coordinate
|
|
|
|
|
|
class SplitType:
|
|
UART = 1
|
|
I2C = 2 # unused
|
|
ONEWIRE = 3 # unused
|
|
BLE = 4 # unused
|
|
|
|
|
|
class Split(Extension):
|
|
def __init__(
|
|
self,
|
|
extra_data_pin=None,
|
|
offsets=(),
|
|
flip=False,
|
|
side=None,
|
|
stype=None,
|
|
master_left=True,
|
|
uart_flip=True,
|
|
uart_pin=None,
|
|
uart_timeout=20,
|
|
):
|
|
self.extra_data_pin = extra_data_pin
|
|
self.split_offsets = offsets
|
|
self.split_flip = flip
|
|
self.split_side = side
|
|
self.split_type = stype
|
|
self.split_master_left = master_left
|
|
self._uart = None
|
|
self.uart_flip = uart_flip
|
|
self.uart_pin = uart_pin
|
|
self.uart_timeout = uart_timeout
|
|
|
|
def during_bootup(self, keyboard):
|
|
if self.split_type is not None:
|
|
try:
|
|
# Working around https://github.com/adafruit/circuitpython/issues/1769
|
|
keyboard._hid_helper_inst.create_report([]).send()
|
|
self._is_master = True
|
|
|
|
# Sleep 2s so master portion doesn't "appear" to boot quicker than
|
|
# dependent portions (which will take ~2s to time out on the HID send)
|
|
sleep_ms(2000)
|
|
except OSError:
|
|
self._is_master = False
|
|
|
|
if self.split_flip and not self._is_master:
|
|
keyboard.col_pins = list(reversed(self.col_pins))
|
|
if self.split_side == 'Left':
|
|
self.split_master_left = self._is_master
|
|
elif self.split_side == 'Right':
|
|
self.split_master_left = not self._is_master
|
|
else:
|
|
self._is_master = True
|
|
|
|
if self.uart_pin is not None:
|
|
if self._is_master:
|
|
self._uart = busio.UART(
|
|
tx=None, rx=self.uart_pin, timeout=self.uart_timeout
|
|
)
|
|
else:
|
|
self._uart = busio.UART(
|
|
tx=self.uart_pin, rx=None, timeout=self.uart_timeout
|
|
)
|
|
|
|
# Attempt to sanely guess a coord_mapping if one is not provided.
|
|
if not keyboard.coord_mapping:
|
|
keyboard.coord_mapping = []
|
|
|
|
rows_to_calc = len(keyboard.row_pins)
|
|
cols_to_calc = len(keyboard.col_pins)
|
|
|
|
if self.split_offsets:
|
|
rows_to_calc *= 2
|
|
cols_to_calc *= 2
|
|
|
|
for ridx in range(rows_to_calc):
|
|
for cidx in range(cols_to_calc):
|
|
keyboard.coord_mapping.append(intify_coordinate(ridx, cidx))
|
|
|
|
gc.collect()
|
|
|
|
def before_matrix_scan(self, keyboard_state):
|
|
if self.split_type is not None and self._is_master:
|
|
return self._receive_from_slave()
|
|
|
|
def after_matrix_scan(self, keyboard_state, matrix_update):
|
|
if matrix_update is not None and not self._is_master:
|
|
self._send_to_master(matrix_update)
|
|
|
|
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)
|