117 lines
3.4 KiB
Python
Executable File
117 lines
3.4 KiB
Python
Executable File
from adafruit_hid.keyboard import Keyboard
|
|
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS
|
|
from adafruit_hid.keycode import Keycode
|
|
from adafruit_rgbled import RGBLED
|
|
import digitalio
|
|
from adafruit_mcp230xx.mcp23017 import MCP23017
|
|
import busio
|
|
import board
|
|
import usb_hid
|
|
|
|
|
|
PRESSED = False
|
|
UNPRESSED = True
|
|
|
|
MCP_ADDRESS = 32
|
|
|
|
PINOUT = [
|
|
[7, 11, 15, 0],
|
|
[8, 4, 14, 1],
|
|
[6, 10, 13, 2],
|
|
[9, 5, 12, 3]
|
|
]
|
|
|
|
|
|
class KeyboardStateManager:
|
|
active_layer: int
|
|
state: list[list[int]]
|
|
keymap: list[list[Keycode]]
|
|
pinout: list[list[int]]
|
|
pins: list[list[digitalio.DigitalInOut]]
|
|
keyboard: Keyboard
|
|
keyboard_layout: KeyboardLayoutUS
|
|
mcp: MCP23017
|
|
led: RGBLED
|
|
|
|
def __init__(self, keymap: list[list[Keycode]]):
|
|
self.keymap = keymap
|
|
self.keyboard = Keyboard(usb_hid.devices)
|
|
self.keyboard_layout = KeyboardLayoutUS(self.keyboard)
|
|
self.initialize_io_extender()
|
|
self.initialize_pins(PINOUT)
|
|
self.initialize_led()
|
|
|
|
def initialize_led(self) -> None:
|
|
self.led = RGBLED(board.LED_R, board.LED_G, board.LED_B, True)
|
|
self.reset_led()
|
|
|
|
def initialize_io_extender(self) -> None:
|
|
self.mcp = MCP23017(busio.I2C(board.GP1, board.GP0), MCP_ADDRESS)
|
|
|
|
def initialize_pins(self, pinout: list[list[int]]) -> None:
|
|
self.pinout = pinout
|
|
self.pins = []
|
|
self.state = []
|
|
for pinout_row in self.pinout:
|
|
pin_row = []
|
|
previous_state_row = []
|
|
for pinout in pinout_row:
|
|
pin = self.mcp.get_pin(pinout)
|
|
pin.direction = digitalio.Direction.INPUT
|
|
pin.pull = digitalio.Pull.UP
|
|
pin_row.append(pin)
|
|
previous_state_row.append(UNPRESSED)
|
|
self.pins.append(pin_row)
|
|
self.state.append(previous_state_row)
|
|
|
|
def loop(self):
|
|
for row in self.pins:
|
|
for pin in row:
|
|
row_index, pin_index = self.pins.index(row), row.index(pin)
|
|
keycode = self.keymap[row_index][pin_index]
|
|
previously = self.state[row_index][pin_index]
|
|
key = pin.value == UNPRESSED
|
|
|
|
if key is PRESSED:
|
|
if previously is UNPRESSED:
|
|
self.keyboard.press(keycode)
|
|
self.set_led((1, 0, 0))
|
|
if key is UNPRESSED:
|
|
if previously is PRESSED:
|
|
self.keyboard.release(keycode)
|
|
self.reset_led()
|
|
self.state[row_index][pin_index] = key
|
|
|
|
def set_led(self, value: tuple[int, int, int]):
|
|
self.led.color = value
|
|
|
|
def reset_led(self):
|
|
self.led.color = (0, 255, 0)
|
|
|
|
# Create interface for key of different type
|
|
# interface has method to handle keypress and release and gets access to key keyboards state and keyboard instance
|
|
# keyboard state should be increased with layer
|
|
# layer keys take a type, a set layer, and a color combination
|
|
|
|
# class LayerKeyType(Enum):
|
|
# hold = 1
|
|
# toggle = 2
|
|
|
|
# def handle_key(raw_keymap:list[list]]):
|
|
# for row in raw_keymap:
|
|
# for key in row:
|
|
# if key in Keycode:
|
|
# # handle as keycode
|
|
# pass
|
|
# if key.
|
|
|
|
|
|
# class LayerKey:
|
|
# type: LayerKeyType
|
|
|
|
# def __init__(self, type: LayerKeyType, layer: int):
|
|
|
|
# class KeycodeKey:
|
|
# def __init__(self):
|
|
# pass
|