Refactor MatrixScanner to use enhanced Pins abstraction; add DEBUG_ENABLED to SAMD51 boards
This commit is contained in:
		@@ -1,9 +0,0 @@
 | 
			
		||||
from kmk.common.consts import DiodeOrientation
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AbstractMatrixScanner():
 | 
			
		||||
    def __init__(self, cols, rows, active_layers, diode_orientation=DiodeOrientation.COLUMNS):
 | 
			
		||||
        raise NotImplementedError('Abstract implementation')
 | 
			
		||||
 | 
			
		||||
    def scan_for_pressed(self):
 | 
			
		||||
        raise NotImplementedError('Abstract implementation')
 | 
			
		||||
@@ -1,3 +1,7 @@
 | 
			
		||||
CIRCUITPYTHON = 'CircuitPython'
 | 
			
		||||
MICROPYTHON = 'MicroPython'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class HIDReportTypes:
 | 
			
		||||
    KEYBOARD = 1
 | 
			
		||||
    MOUSE = 2
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,10 @@
 | 
			
		||||
import digitalio
 | 
			
		||||
 | 
			
		||||
from kmk.common.abstract.matrix_scanner import AbstractMatrixScanner
 | 
			
		||||
from kmk.common.consts import DiodeOrientation
 | 
			
		||||
from kmk.common.event_defs import matrix_changed
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MatrixScanner(AbstractMatrixScanner):
 | 
			
		||||
class MatrixScanner:
 | 
			
		||||
    def __init__(self, cols, rows, diode_orientation=DiodeOrientation.COLUMNS):
 | 
			
		||||
        # A pin cannot be both a row and column, detect this by combining the
 | 
			
		||||
        # two tuples into a set and validating that the length did not drop
 | 
			
		||||
@@ -15,8 +14,8 @@ class MatrixScanner(AbstractMatrixScanner):
 | 
			
		||||
        if len(unique_pins) != len(cols) + len(rows):
 | 
			
		||||
            raise ValueError('Cannot use a pin as both a column and row')
 | 
			
		||||
 | 
			
		||||
        self.cols = [digitalio.DigitalInOut(pin) for pin in cols]
 | 
			
		||||
        self.rows = [digitalio.DigitalInOut(pin) for pin in rows]
 | 
			
		||||
        self.cols = cols
 | 
			
		||||
        self.rows = rows
 | 
			
		||||
        self.diode_orientation = diode_orientation
 | 
			
		||||
        self.last_pressed_len = 0
 | 
			
		||||
 | 
			
		||||
@@ -41,15 +40,15 @@ class MatrixScanner(AbstractMatrixScanner):
 | 
			
		||||
        pressed = []
 | 
			
		||||
 | 
			
		||||
        for oidx, opin in enumerate(self.outputs):
 | 
			
		||||
            opin.value = True
 | 
			
		||||
            opin.value(True)
 | 
			
		||||
 | 
			
		||||
            for iidx, ipin in enumerate(self.inputs):
 | 
			
		||||
                if ipin.value:
 | 
			
		||||
                if ipin.value():
 | 
			
		||||
                    pressed.append(
 | 
			
		||||
                        (oidx, iidx) if self.diode_orientation == DiodeOrientation.ROWS else (iidx, oidx)  # noqa
 | 
			
		||||
                    )
 | 
			
		||||
 | 
			
		||||
            opin.value = False
 | 
			
		||||
            opin.value(False)
 | 
			
		||||
 | 
			
		||||
        if len(pressed) != self.last_pressed_len:
 | 
			
		||||
            self.last_pressed_len = len(pressed)
 | 
			
		||||
@@ -1,18 +1,22 @@
 | 
			
		||||
from micropython import const
 | 
			
		||||
 | 
			
		||||
from kmk.common.consts import CIRCUITPYTHON, MICROPYTHON
 | 
			
		||||
 | 
			
		||||
PULL_UP = const(1)
 | 
			
		||||
PULL_DOWN = const(2)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
try:
 | 
			
		||||
    import board
 | 
			
		||||
    import digitalio
 | 
			
		||||
 | 
			
		||||
    PLATFORM = 'CircuitPython'
 | 
			
		||||
    PLATFORM = CIRCUITPYTHON
 | 
			
		||||
    PIN_SOURCE = board
 | 
			
		||||
except ImportError:
 | 
			
		||||
    import machine
 | 
			
		||||
 | 
			
		||||
    PLATFORM = 'MicroPython'
 | 
			
		||||
    PLATFORM = MICROPYTHON
 | 
			
		||||
    PIN_SOURCE = machine.Pin.board
 | 
			
		||||
except ImportError:
 | 
			
		||||
    from kmk.common.types import Passthrough
 | 
			
		||||
 | 
			
		||||
    PLATFORM = 'Unit Testing'
 | 
			
		||||
    PIN_SOURCE = Passthrough()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_pin(pin):
 | 
			
		||||
@@ -32,9 +36,64 @@ def get_pin(pin):
 | 
			
		||||
    return getattr(PIN_SOURCE, pin)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AbstractedDigitalPin:
 | 
			
		||||
    def __init__(self, pin):
 | 
			
		||||
        self.raw_pin = pin
 | 
			
		||||
 | 
			
		||||
        if PLATFORM == CIRCUITPYTHON:
 | 
			
		||||
            self.pin = digitalio.DigitalInOut(pin)
 | 
			
		||||
        elif PLATFORM == MICROPYTHON:
 | 
			
		||||
            self.pin = machine.Pin(pin)
 | 
			
		||||
        else:
 | 
			
		||||
            self.pin = pin
 | 
			
		||||
 | 
			
		||||
        self.call_value = callable(self.pin.value)
 | 
			
		||||
 | 
			
		||||
    def __repr__(self):
 | 
			
		||||
        return 'AbstractedPin({})'.format(repr(self.raw_pin))
 | 
			
		||||
 | 
			
		||||
    def switch_to_input(self, pull=None):
 | 
			
		||||
        if PLATFORM == CIRCUITPYTHON:
 | 
			
		||||
            if pull == PULL_UP:
 | 
			
		||||
                return self.pin.switch_to_input(pull=digitalio.Pull.UP)
 | 
			
		||||
            elif pull == PULL_DOWN:
 | 
			
		||||
                return self.pin.switch_to_input(pull=digitalio.Pull.DOWN)
 | 
			
		||||
 | 
			
		||||
            return self.pin.switch_to_input(pull=pull)
 | 
			
		||||
 | 
			
		||||
        elif PLATFORM == MICROPYTHON:
 | 
			
		||||
            if pull == PULL_UP:
 | 
			
		||||
                return self.pin.init(machine.Pin.IN, machine.Pin.PULL_UP)
 | 
			
		||||
            elif pull == PULL_DOWN:
 | 
			
		||||
                return self.pin.init(machine.Pin.IN, machine.Pin.PULL_DOWN)
 | 
			
		||||
 | 
			
		||||
            raise ValueError('only PULL_UP and PULL_DOWN supported on MicroPython')
 | 
			
		||||
 | 
			
		||||
        raise NotImplementedError('switch_to_input not supported on platform')
 | 
			
		||||
 | 
			
		||||
    def switch_to_output(self):
 | 
			
		||||
        if PLATFORM == CIRCUITPYTHON:
 | 
			
		||||
            return self.pin.switch_to_output()
 | 
			
		||||
        elif PLATFORM == MICROPYTHON:
 | 
			
		||||
            return self.pin.init(machine.Pin.OUT)
 | 
			
		||||
 | 
			
		||||
        raise NotImplementedError('switch_to_output not supported on platform')
 | 
			
		||||
 | 
			
		||||
    def value(self, value=None):
 | 
			
		||||
        if value is None:
 | 
			
		||||
            if self.call_value:
 | 
			
		||||
                return self.pin.value()
 | 
			
		||||
            return self.pin.value
 | 
			
		||||
 | 
			
		||||
        if self.call_value:
 | 
			
		||||
            return self.pin.value(value)
 | 
			
		||||
        self.pin.value = value
 | 
			
		||||
        return value
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PinLookup:
 | 
			
		||||
    def __getattr__(self, attr):
 | 
			
		||||
        return get_pin(attr)
 | 
			
		||||
        return AbstractedDigitalPin(get_pin(attr))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Pin = PinLookup()
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,24 @@
 | 
			
		||||
import sys
 | 
			
		||||
from logging import WARNING
 | 
			
		||||
 | 
			
		||||
from kmk.circuitpython.hid import HIDHelper
 | 
			
		||||
from kmk.circuitpython.matrix import MatrixScanner
 | 
			
		||||
from kmk.common.consts import UnicodeModes
 | 
			
		||||
from kmk.common.matrix import MatrixScanner
 | 
			
		||||
from kmk.firmware import Firmware
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def main():
 | 
			
		||||
    from kmk_keyboard_user import cols, diode_orientation, keymap, rows
 | 
			
		||||
    import kmk_keyboard_user
 | 
			
		||||
    cols = getattr(kmk_keyboard_user, 'cols')
 | 
			
		||||
    diode_orientation = getattr(kmk_keyboard_user, 'diode_orientation')
 | 
			
		||||
    keymap = getattr(kmk_keyboard_user, 'keymap')
 | 
			
		||||
    rows = getattr(kmk_keyboard_user, 'rows')
 | 
			
		||||
 | 
			
		||||
    DEBUG_ENABLE = getattr(kmk_keyboard_user, 'DEBUG_ENABLE', False)
 | 
			
		||||
 | 
			
		||||
    if DEBUG_ENABLE:
 | 
			
		||||
        from logging import DEBUG as log_level
 | 
			
		||||
    else:
 | 
			
		||||
        from logging import ERROR as log_level
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        from kmk_keyboard_user import unicode_mode
 | 
			
		||||
@@ -22,7 +32,7 @@ def main():
 | 
			
		||||
            col_pins=cols,
 | 
			
		||||
            diode_orientation=diode_orientation,
 | 
			
		||||
            unicode_mode=unicode_mode,
 | 
			
		||||
            log_level=WARNING,
 | 
			
		||||
            log_level=log_level,
 | 
			
		||||
            matrix_scanner=MatrixScanner,
 | 
			
		||||
            hid=HIDHelper,
 | 
			
		||||
        )
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,24 @@
 | 
			
		||||
import sys
 | 
			
		||||
from logging import WARNING
 | 
			
		||||
 | 
			
		||||
from kmk.circuitpython.hid import HIDHelper
 | 
			
		||||
from kmk.circuitpython.matrix import MatrixScanner
 | 
			
		||||
from kmk.common.consts import UnicodeModes
 | 
			
		||||
from kmk.common.matrix import MatrixScanner
 | 
			
		||||
from kmk.firmware import Firmware
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def main():
 | 
			
		||||
    from kmk_keyboard_user import cols, diode_orientation, keymap, rows
 | 
			
		||||
    import kmk_keyboard_user
 | 
			
		||||
    cols = getattr(kmk_keyboard_user, 'cols')
 | 
			
		||||
    diode_orientation = getattr(kmk_keyboard_user, 'diode_orientation')
 | 
			
		||||
    keymap = getattr(kmk_keyboard_user, 'keymap')
 | 
			
		||||
    rows = getattr(kmk_keyboard_user, 'rows')
 | 
			
		||||
 | 
			
		||||
    DEBUG_ENABLE = getattr(kmk_keyboard_user, 'DEBUG_ENABLE', False)
 | 
			
		||||
 | 
			
		||||
    if DEBUG_ENABLE:
 | 
			
		||||
        from logging import DEBUG as log_level
 | 
			
		||||
    else:
 | 
			
		||||
        from logging import ERROR as log_level
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        from kmk_keyboard_user import unicode_mode
 | 
			
		||||
@@ -22,7 +32,7 @@ def main():
 | 
			
		||||
            col_pins=cols,
 | 
			
		||||
            diode_orientation=diode_orientation,
 | 
			
		||||
            unicode_mode=unicode_mode,
 | 
			
		||||
            log_level=WARNING,
 | 
			
		||||
            log_level=log_level,
 | 
			
		||||
            matrix_scanner=MatrixScanner,
 | 
			
		||||
            hid=HIDHelper,
 | 
			
		||||
        )
 | 
			
		||||
 
 | 
			
		||||
@@ -2,8 +2,8 @@ import sys
 | 
			
		||||
 | 
			
		||||
import gc
 | 
			
		||||
 | 
			
		||||
from kmk.common.matrix import MatrixScanner
 | 
			
		||||
from kmk.firmware import Firmware
 | 
			
		||||
from kmk.micropython.matrix import MatrixScanner
 | 
			
		||||
from kmk.micropython.pyb_hid import HIDHelper
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -17,9 +17,9 @@ def main():
 | 
			
		||||
    DEBUG_ENABLE = getattr(kmk_keyboard_user, 'DEBUG_ENABLE', False)
 | 
			
		||||
 | 
			
		||||
    if DEBUG_ENABLE:
 | 
			
		||||
        from logging import DEBUG
 | 
			
		||||
        from logging import DEBUG as log_level
 | 
			
		||||
    else:
 | 
			
		||||
        from logging import ERROR as DEBUG
 | 
			
		||||
        from logging import ERROR as log_level
 | 
			
		||||
 | 
			
		||||
    # This will run out of ram at this point unless you manually GC
 | 
			
		||||
    gc.collect()
 | 
			
		||||
@@ -31,7 +31,7 @@ def main():
 | 
			
		||||
            col_pins=cols,
 | 
			
		||||
            diode_orientation=diode_orientation,
 | 
			
		||||
            hid=HIDHelper,
 | 
			
		||||
            log_level=DEBUG,
 | 
			
		||||
            log_level=log_level,
 | 
			
		||||
            matrix_scanner=MatrixScanner,
 | 
			
		||||
        )
 | 
			
		||||
        # This will run out of ram at this point unless you manually GC
 | 
			
		||||
 
 | 
			
		||||
@@ -1,63 +0,0 @@
 | 
			
		||||
import machine
 | 
			
		||||
 | 
			
		||||
from kmk.common.abstract.matrix_scanner import AbstractMatrixScanner
 | 
			
		||||
from kmk.common.consts import DiodeOrientation
 | 
			
		||||
from kmk.common.event_defs import matrix_changed
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MatrixScanner(AbstractMatrixScanner):
 | 
			
		||||
    def __init__(self, cols, rows, active_layers, diode_orientation=DiodeOrientation.COLUMNS):
 | 
			
		||||
        # A pin cannot be both a row and column, detect this by combining the
 | 
			
		||||
        # two tuples into a set and validating that the length did not drop
 | 
			
		||||
        #
 | 
			
		||||
        # repr() hackery is because MicroPython Pin objects are not hashable.
 | 
			
		||||
        # Technically we support passing either a string (hashable) or the
 | 
			
		||||
        # Pin object directly here, so the hackaround is necessary.
 | 
			
		||||
        unique_pins = {repr(c) for c in cols} | {repr(r) for r in rows}
 | 
			
		||||
        if len(unique_pins) != len(cols) + len(rows):
 | 
			
		||||
            raise ValueError('Cannot use a pin as both a column and row')
 | 
			
		||||
 | 
			
		||||
        self.cols = [machine.Pin(pin) for pin in cols]
 | 
			
		||||
        self.rows = [machine.Pin(pin) for pin in rows]
 | 
			
		||||
        self.diode_orientation = diode_orientation
 | 
			
		||||
        self.active_layers = active_layers
 | 
			
		||||
        self.last_pressed_len = 0
 | 
			
		||||
 | 
			
		||||
        if self.diode_orientation == DiodeOrientation.COLUMNS:
 | 
			
		||||
            self.outputs = self.cols
 | 
			
		||||
            self.inputs = self.rows
 | 
			
		||||
        elif self.diode_orientation == DiodeOrientation.ROWS:
 | 
			
		||||
            self.outputs = self.rows
 | 
			
		||||
            self.inputs = self.cols
 | 
			
		||||
        else:
 | 
			
		||||
            raise ValueError('Invalid DiodeOrientation: {}'.format(
 | 
			
		||||
                self.diode_orientation,
 | 
			
		||||
            ))
 | 
			
		||||
 | 
			
		||||
        for pin in self.outputs:
 | 
			
		||||
            pin.init(machine.Pin.OUT)
 | 
			
		||||
            pin.off()
 | 
			
		||||
 | 
			
		||||
        for pin in self.inputs:
 | 
			
		||||
            pin.init(machine.Pin.IN, machine.Pin.PULL_DOWN)
 | 
			
		||||
            pin.off()
 | 
			
		||||
 | 
			
		||||
    def scan_for_pressed(self):
 | 
			
		||||
        pressed = []
 | 
			
		||||
 | 
			
		||||
        for oidx, opin in enumerate(self.outputs):
 | 
			
		||||
            opin.value(1)
 | 
			
		||||
 | 
			
		||||
            for iidx, ipin in enumerate(self.inputs):
 | 
			
		||||
                if ipin.value():
 | 
			
		||||
                    pressed.append(
 | 
			
		||||
                        (oidx, iidx) if self.diode_orientation == DiodeOrientation.ROWS else (iidx, oidx)  # noqa
 | 
			
		||||
                    )
 | 
			
		||||
 | 
			
		||||
            opin.value(0)
 | 
			
		||||
 | 
			
		||||
        if len(pressed) != self.last_pressed_len:
 | 
			
		||||
            self.last_pressed_len = len(pressed)
 | 
			
		||||
            return matrix_changed(pressed)
 | 
			
		||||
 | 
			
		||||
        return None  # The default, but for explicitness
 | 
			
		||||
@@ -5,9 +5,16 @@ class Anything:
 | 
			
		||||
    def __init__(self, name):
 | 
			
		||||
        self.name = name
 | 
			
		||||
 | 
			
		||||
    def __call__(self, *args, **kwargs):
 | 
			
		||||
        return self
 | 
			
		||||
 | 
			
		||||
    def __repr__(self):
 | 
			
		||||
        return 'Anything<{}>'.format(self.name)
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def value(self):
 | 
			
		||||
        return None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Passthrough:
 | 
			
		||||
    def __getattr__(self, attr):
 | 
			
		||||
@@ -16,3 +23,9 @@ class Passthrough:
 | 
			
		||||
 | 
			
		||||
class Pin:
 | 
			
		||||
    board = Passthrough()
 | 
			
		||||
 | 
			
		||||
    def __call__(self, *args, **kwargs):
 | 
			
		||||
        return self.board
 | 
			
		||||
 | 
			
		||||
    def __getattr__(self, attr):
 | 
			
		||||
        return getattr(self.board, attr)
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,8 @@ from kmk.common.types import AttrDict
 | 
			
		||||
from kmk.entrypoints.handwire.itsybitsy_m4_express import main
 | 
			
		||||
from kmk.firmware import Firmware
 | 
			
		||||
 | 
			
		||||
DEBUG_ENABLE = True
 | 
			
		||||
 | 
			
		||||
cols = (P.A4, P.A5, P.D7)
 | 
			
		||||
rows = (P.D12, P.D11, P.D10)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user