Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

USB NKRO example for MacroPad #1620

Merged
merged 1 commit into from
Jul 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions CircuitPython_MacroPad_NKRO/boot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import usb_hid

BITMAP_KEYBOARD_DESCRIPTOR_REPORT_ID = 7
REPORT_BYTES = 16
bitmap_keyboard_descriptor = bytes((
0x05, 0x01, # Usage Page (Generic Desktop),
0x09, 0x06, # Usage (Keyboard),
0xA1, 0x01, # Collection (Application),
0x85, 0xFF, # 6,7 Report ID [SET AT RUNTIME]
# bitmap of modifiers
0x75, 0x01, # Report Size (1),
0x95, 0x08, # Report Count (8),
0x05, 0x07, # Usage Page (Key Codes),
0x19, 0xE0, # Usage Minimum (224),
0x29, 0xE7, # Usage Maximum (231),
0x15, 0x00, # Logical Minimum (0),
0x25, 0x01, # Logical Maximum (1),
0x81, 0x02, # Input (Data, Variable, Absolute), ;Modifier byte
# LED output report
0x95, 0x05, # Report Count (5),
0x75, 0x01, # Report Size (1),
0x05, 0x08, # Usage Page (LEDs),
0x19, 0x01, # Usage Minimum (1),
0x29, 0x05, # Usage Maximum (5),
0x91, 0x02, # Output (Data, Variable, Absolute),
0x95, 0x01, # Report Count (1),
0x75, 0x03, # Report Size (3),
0x91, 0x03, # Output (Constant),
# bitmap of keys
0x95, (REPORT_BYTES-1)*8, # Report Count (),
0x75, 0x01, # Report Size (1),
0x15, 0x00, # Logical Minimum (0),
0x25, 0x01, # Logical Maximum(1),
0x05, 0x07, # Usage Page (Key Codes),
0x19, 0x00, # Usage Minimum (0),
0x29, (REPORT_BYTES-1)*8-1, # Usage Maximum (),
0x81, 0x02, # Input (Data, Variable, Absolute),
0xc0 # End Collection
))

bitmap_keyboard = usb_hid.Device(
report_descriptor = bitmap_keyboard_descriptor,
usage_page = 0x1,
usage = 0x6,
in_report_length = 16,
out_report_length = 1,
report_id_index = BITMAP_KEYBOARD_DESCRIPTOR_REPORT_ID,
)

print(bitmap_keyboard)
devices = [
bitmap_keyboard,
usb_hid.Device.CONSUMER_CONTROL,
usb_hid.Device.MOUSE,
]
usb_hid.enable(devices)
print("enabled HID with custom keyboard device")
78 changes: 78 additions & 0 deletions CircuitPython_MacroPad_NKRO/code.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import keypad
import board
import usb_hid
from adafruit_hid.keyboard import Keyboard, find_device
from adafruit_hid.keycode import Keycode

key_pins = (
board.KEY1,
board.KEY2,
board.KEY3,
board.KEY4,
board.KEY5,
board.KEY6,
board.KEY7,
board.KEY8,
board.KEY9,
board.KEY10,
board.KEY11,
board.KEY12,
)

keys = keypad.Keys(key_pins, value_when_pressed=False, pull=True)

class BitmapKeyboard(Keyboard):
def __init__(self, devices):
device = find_device(devices, usage_page=0x1, usage=0x6)

try:
device.send_report(b'\0' * 16)
except ValueError:
print("found keyboard, but it did not accept a 16-byte report. check that boot.py is installed properly")

self._keyboard_device = device

# report[0] modifiers
# report[1:16] regular key presses bitmask
self.report = bytearray(16)

self.report_modifier = memoryview(self.report)[0:1]
self.report_bitmap = memoryview(self.report)[1:]

def _add_keycode_to_report(self, keycode):
modifier = Keycode.modifier_bit(keycode)
if modifier:
# Set bit for this modifier.
self.report_modifier[0] |= modifier
else:
self.report_bitmap[keycode >> 3] |= 1 << (keycode & 0x7)

def _remove_keycode_from_report(self, keycode):
modifier = Keycode.modifier_bit(keycode)
if modifier:
# Set bit for this modifier.
self.report_modifier[0] &= ~modifier
else:
self.report_bitmap[keycode >> 3] &= ~(1 << (keycode & 0x7))

def release_all(self):
for i in range(len(self.report)):
self.report[i] = 0
self._keyboard_device.send_report(self.report)

kbd = BitmapKeyboard(usb_hid.devices)

keymap = [
Keycode.ONE, Keycode.TWO, Keycode.THREE,
Keycode.Q, Keycode.W, Keycode.E,
Keycode.A, Keycode.S, Keycode.D,
Keycode.Z, Keycode.X, Keycode.C]

while True:
ev = keys.events.get()
if ev is not None:
key = keymap[ev.key_number]
if ev.pressed:
kbd.press(key)
else:
kbd.release(key)