prelim module support

This commit is contained in:
Kyle Brown
2020-11-12 14:33:39 -08:00
parent a85ec2cc3f
commit 8839c1c7ec
13 changed files with 235 additions and 159 deletions

133
kmk/modules/split.py Normal file
View File

@@ -0,0 +1,133 @@
import busio
from kmk.matrix import intify_coordinate
from kmk.modules import Module
from storage import getmount
class SplitType:
UART = 1
I2C = 2 # unused
ONEWIRE = 3 # unused
class Split(Module):
def __init__(
self,
is_target=True,
extra_data_pin=None,
split_offset=None,
split_flip=True,
split_side=None,
split_type=SplitType.UART,
target_left=True,
uart_flip=True,
uart_pin=None,
uart_pin2=None,
uart_timeout=20,
):
self._is_target = is_target
self.extra_data_pin = extra_data_pin
self.split_offsets = split_offset
self.split_flip = split_flip
self.split_side = split_side
self.split_type = split_type
self.split_target_left = target_left
self._uart = None
self._uart_buffer = []
self.uart_flip = uart_flip
self.uart_pin = uart_pin
self.uart_pin2 = uart_pin2
self.uart_timeout = uart_timeout
def during_bootup(self, keyboard):
try:
# Working around https://github.com/adafruit/circuitpython/issues/1769
keyboard._hid_helper_inst.create_report([]).send()
# Line above is broken and needs fixed for aut detection
self._is_target = True
except OSError:
self._is_target = False
if self.split_side is None:
l_or_r = str(getmount('/').label)
if l_or_r.endswith('L'):
# If name ends in 'L' assume left and strip from name
self.split_side = 0
elif l_or_r.endswith('R'):
# If name ends in 'R' assume right and strip from name
self.split_side = 1
if self.split_flip and not self._is_target:
keyboard.col_pins = list(reversed(keyboard.col_pins))
if self.split_side == 0:
self.split_target_left = self._is_target
elif self.split_side == 1:
self.split_target_left = not self._is_target
if self.uart_pin is not None:
if self._is_target:
self._uart = busio.UART(
tx=self.uart_pin2, rx=self.uart_pin, timeout=self.uart_timeout
)
else:
self._uart = busio.UART(
tx=self.uart_pin, rx=self.uart_pin2, timeout=self.uart_timeout
)
# Attempt to sanely guess a coord_mapping if one is not provided.
if not keyboard.coord_mapping:
keyboard.coord_mapping = []
self.split_offset = len(keyboard.col_pins)
rows_to_calc = len(keyboard.row_pins) * 2
cols_to_calc = len(keyboard.col_pins) * 2
for ridx in range(rows_to_calc):
for cidx in range(cols_to_calc):
keyboard.coord_mapping.append(intify_coordinate(ridx, cidx))
def before_matrix_scan(self, keyboard):
if self._is_target or self.uart_pin2:
return self._receive(keyboard)
return None
def after_matrix_scan(self, keyboard):
if keyboard.matrix_update is not None and not self._is_target:
self._send(keyboard.matrix_update)
def before_hid_send(self, keyboard):
return
def after_hid_send(self, keyboard):
return
def on_powersave_enable(self, keyboard):
return
def on_powersave_disable(self, keyboard):
return
def _send(self, update):
if self.split_target_left:
update[1] += self.split_offset
else:
update[1] -= self.split_offsets
if self._uart is not None:
self._uart.write(update)
def _receive(self, keyboard):
if self._uart is not None and self._uart.in_waiting > 0 or self._uart_buffer:
if self._uart.in_waiting >= 60:
# This is a dirty hack to prevent crashes in unrealistic cases
import microcontroller
microcontroller.reset()
while self._uart.in_waiting >= 3:
self._uart_buffer.append(self._uart.read(3))
if self._uart_buffer:
keyboard.secondary_matrix_update = bytearray(self._uart_buffer.pop(0))
return
return None