Custom matrix scanners

- Introduce Scanner base class for MatrixScanner
- Create new Scanner using built-in keypad module
- Allow overriding the scanner used by KMKKeyboard
This commit is contained in:
Ellie
2021-10-04 01:40:18 +11:00
committed by Kyle Brown
parent e7d306cf30
commit 57ba0fe8b2
5 changed files with 153 additions and 7 deletions

View File

@@ -290,12 +290,18 @@ class KMKKeyboard:
self._hid_send_enabled = True
def _init_matrix(self):
self.matrix = self.matrix_scanner(
cols=self.col_pins,
rows=self.row_pins,
diode_orientation=self.diode_orientation,
rollover_cols_every_rows=getattr(self, 'rollover_cols_every_rows', None),
)
if self.matrix is None:
print('Initialising matrix scanner from self.matrix_scanner')
self.matrix = self.matrix_scanner(
cols=self.col_pins,
rows=self.row_pins,
diode_orientation=self.diode_orientation,
rollover_cols_every_rows=getattr(
self, 'rollover_cols_every_rows', None
),
)
else:
print('Matrix scanner already set, not overwriting.')
return self

View File

@@ -1,5 +1,7 @@
import digitalio
from kmk.scanners import Scanner
def intify_coordinate(row, col, len_cols):
return len_cols * row + col
@@ -26,7 +28,7 @@ class KeyEvent:
self.pressed = pressed
class MatrixScanner:
class MatrixScanner(Scanner):
def __init__(
self,
cols,

12
kmk/scanners/__init__.py Normal file
View File

@@ -0,0 +1,12 @@
class Scanner:
'''
Base class for scanners.
'''
def scan_for_changes(self):
'''
Scan for key events and return a key report if an event exists.
The key report is a byte array with contents [row, col, True if pressed else False]
'''
pass

View File

@@ -0,0 +1,60 @@
import keypad
from kmk.matrix import DiodeOrientation
from kmk.scanners import Scanner
class NativeKeypadScanner(Scanner):
'''
Translation layer around a CircuitPython 7 keypad scanner.
:param pin_map: A sequence of (row, column) tuples for each key.
:param kp: An instance of the keypad class.
'''
def __init__(self, pin_map, kp):
self.pin_map = pin_map
self.keypad = kp
# self.coord_mapping = [ic(row, col) for (row, col) in self.pin_map]
self.coord_mapping = list(range(len(pin_map)))
self.curr_event = keypad.Event()
def scan_for_changes(self):
'''
Scan for key events and return a key report if an event exists.
The key report is a byte array with contents [row, col, True if pressed else False]
'''
ev = self.curr_event
has_event = self.keypad.events.get_into(ev)
if has_event:
return ev
def keypad_matrix(row_pins, col_pins, direction=DiodeOrientation.COLUMNS):
'''
Row/Column matrix using the CircuitPython 7 keypad scanner.
:param row_pins: A sequence of pins used for rows.
:param col_pins: A sequence of pins used for columns.
:param direction: The diode orientation of the matrix.
'''
pin_map = [
(row, col) for row in range(len(row_pins)) for col in range(len(col_pins))
]
kp = keypad.KeyMatrix(row_pins, col_pins, direction == DiodeOrientation.COLUMNS)
return NativeKeypadScanner(pin_map, kp)
def keys_scanner(pins):
'''
GPIO-per-key 'matrix' using the native CircuitPython 7 keypad scanner.
:param pins: An array of arrays of CircuitPython Pin objects, such that pins[r][c] is the pin for row r, column c.
'''
pin_map = [(row, col) for row in range(len(pins)) for col in range(len(pins[row]))]
kp = keypad.Keys(
[pins[r][c] for (r, c) in pin_map], value_when_pressed=False, pull=True
)
return NativeKeypadScanner(pin_map, kp)