import asyncio
import board
from digitalio import Direction, DigitalInOut, Pull, DriveMode
import usb_hid
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keycode import Keycode
kbd = Keyboard(usb_hid.devices)
blink_state = False # Global for if blinking lights should be lit or not.
eventStack = [] # List of events to fire
keys_pressed = []
class LED:
def __init__(self, pin):
self.pin = DigitalInOut(pin)
self.pin.direction = Direction.OUTPUT
self.blink = False
def toggle(self):
self.pin.value = not self.pin.value
def set_state(self, state):
self.pin.value = state
def toggle_blink(self):
self.blink = not self.blink
self.pin.value = blink_state
class InputKey:
def __init__(self, key_pin, scan_code, name, led, keyboard = kbd):
self.pin = DigitalInOut(key_pin) # What pin is it connected to
self.pin.direction = Direction.INPUT
self.pin.pull = Pull.DOWN
self.scan = scan_code # What keypress should it send?
self.name = name # What should we label it?
self.keyboard = keyboard # What keyboard object are we using, if any
self.led = led
def send_key_press(self):
self.keyboard.send(self.scan)
return self.name
class Event: # barebones event class
def __init__(self):
self.executed = False
def fire(self):
pass # generic fire function
class KeyEvent(Event):
def __init__(self, keyPress):
super().__init__()
self.keyPress = keyPress
def fire(self):
self.keyPress.send_key_press()
class BlinkEvent(Event):
def __init__(self, light, toggle = False):
self.light = light
self.toggle = toggle
def fire(self):
global blink_state
if self.toggle:
self.light.toggle_blink()
else:
self.light.set_state(blink_state)
class LightEvent(Event):
def __init__(self, light, eventType):
super().__init__()
self.light = light
self.eventType = eventType
def fire(self):
if eventType >= 2:
self.light.toggle()
else:
self.light.set_state(eventType)
async def await_key_press():
while True:
# Poll the keys, see if they're pressed!
for k in key_list:
if k.pin.value:
#It's pressed! Make sure it's not being held:
if not k.name in keys_pressed: # If it's not, flag it as being pressed, and set an event.
keys_pressed.append(k.name)
eventStack.append(KeyEvent(k))
eventStack.append(BlinkEvent(k.led, True)) #dbg
else: # If it's not pressed, drop it from the pressed list
if k.name in keys_pressed:
keys_pressed.remove(k.name)
await asyncio.sleep_ms(50) # fire every 50ms for software anti bounce
async def process_events():
# Async function to process any awaiting events
while True:
if len(eventStack) > 0:
eventStack[0].fire()
eventStack.pop(0)
await asyncio.sleep(0)
async def blinkLEDs():
global blink_state
while True:
blink_state = not blink_state
for light in light_list:
if light.blink:
eventStack.append(BlinkEvent(light))
await asyncio.sleep_ms(500) # half second blink duration
async def main():
key_task = asyncio.create_task(await_key_press())
blink_task = asyncio.create_task(blinkLEDs())
event_task = asyncio.create_task(process_events())
await asyncio.gather(key_task, event_task, blink_task)
light_list = [ # List of LED objects
LED(board.GP0),
LED(board.GP2),
LED(board.GP4),
LED(board.GP6),
LED(board.GP8)
]
key_list = [ # List of input keys
InputKey(board.GP1, Keycode.A, "k1", light_list[0]),
InputKey(board.GP3, Keycode.B, "k1", light_list[1]),
InputKey(board.GP5, Keycode.C, "k1", light_list[2]),
InputKey(board.GP7, Keycode.D, "k1", light_list[3]),
InputKey(board.GP9, Keycode.E, "k1", light_list[4]),
]
asyncio.run(main())