Skip to content

Instantly share code, notes, and snippets.

@wulfboy-95
Last active October 12, 2024 00:30
Show Gist options
  • Save wulfboy-95/12f6bde624bf8b0d97d07888b0b5bd17 to your computer and use it in GitHub Desktop.
Save wulfboy-95/12f6bde624bf8b0d97d07888b0b5bd17 to your computer and use it in GitHub Desktop.
CircuitPython (7.x.x and above) code for a TADA-68 style keyboard with a Raspberry Pi Pico controller.
# Copyright wulfboy_95 2022, All Rights Reserved.
# Copying and distribution of this file, with or without modification,
# are permitted in any medium without royalty provided the copyright
# notice and this notice are preserved. This file is offered as-is,
# without any warranty.
import board
import keypad
import struct
import usb_hid
from adafruit_hid.keyboard import Keycode
# Create and init keyboard USB HID device.
keeb = None
for dev in list(usb_hid.devices):
if ((dev.usage == 0x06) and
(dev.usage_page == 0x01) and
hasattr(dev, "send_report")):
keeb = dev
if keeb == None:
raise Exception("Device cannot be found")
matrix = keypad.KeyMatrix(
row_pins = (
board.GP6, board.GP7, board.GP8, board.GP9, board.GP10
),
column_pins = (
board.GP11, board.GP12, board.GP13, board.GP14, board.GP15,
board.GP16, board.GP17, board.GP18, board.GP19, board.GP20,
board.GP21, board.GP22, board.GP26, board.GP27, board.GP28
),
columns_to_anodes=True
)
# Key list to convert key_number from KeyMatrix events to the corresponding keycode.
keys_list = [
Keycode.ESCAPE, Keycode.ONE, Keycode.TWO, Keycode.THREE, Keycode.FOUR, Keycode.FIVE, Keycode.SIX, Keycode.SEVEN,
Keycode.EIGHT, Keycode.NINE, Keycode.ZERO, Keycode.MINUS, Keycode.EQUALS, Keycode.BACKSPACE, Keycode.GRAVE_ACCENT,
Keycode.TAB, Keycode.Q, Keycode.W, Keycode.E, Keycode.R, Keycode.T, Keycode.Y, Keycode.U, Keycode.I, Keycode.O,
Keycode.P, Keycode.LEFT_BRACKET, Keycode.RIGHT_BRACKET, Keycode.BACKSLASH, Keycode.DELETE, Keycode.CAPS_LOCK,
Keycode.A, Keycode.S, Keycode.D, Keycode.F, Keycode.G, Keycode.H, Keycode.J, Keycode.K, Keycode.L, Keycode.SEMICOLON,
Keycode.QUOTE, Keycode.RETURN, Keycode.ENTER, Keycode.HOME, Keycode.LEFT_SHIFT, Keycode.SHIFT, Keycode.Z, Keycode.X,
Keycode.C, Keycode.V, Keycode.B, Keycode.N, Keycode.M, Keycode.COMMA, Keycode.PERIOD, Keycode.FORWARD_SLASH,
Keycode.RIGHT_SHIFT, Keycode.UP_ARROW, Keycode.END, Keycode.LEFT_CONTROL, Keycode.LEFT_GUI, Keycode.LEFT_ALT,
Keycode.SPACE, Keycode.SPACE, Keycode.SPACE, Keycode.SPACEBAR, Keycode.SPACE, Keycode.SPACE, Keycode.RIGHT_ALT,
Keycode.RIGHT_GUI, Keycode.RIGHT_CONTROL, Keycode.LEFT_ARROW, Keycode.DOWN_ARROW, Keycode.RIGHT_ARROW
] # TODO: use a dictionary instead of a list so that unused buttons do not need placeholders.
keys_pressed = []
modifiers_pressed = []
report_array = [0x00] * 8
while True:
while matrix.events: # Run when there are events queued.
event = matrix.events.get()
key = keys_list[event.key_number]
if event.pressed:
if key >= 0xE0: # Check if modifier is pressed.
modifiers_pressed.append(key) # Add to modifiers_pressed list.
else: # Check if a key is pressed.
keys_pressed.append(key)
if event.released:
if key in keys_pressed:
keys_pressed.remove(key)
if key in modifiers_pressed:
modifiers_pressed.remove(key)
if len(keys_pressed) > 6: # Check for Rollover Error.
for i in range(2,8):
report_array[i] = 0x01 # Add Rollover Error keycode*6 to report.
else:
for i in modifiers_pressed:
report_array[0] |= Keycode.modifier_bit(i) # Add modifiers to report.
for i in range(6):
report_array[i+2] = keys_pressed[i] if i < len(keys_pressed) else 0 # Add keycode to report.
keeb.send_report(struct.pack("8B",*report_array))
report_array = [0x00] * 8
@wulfboy-95
Copy link
Author

wulfboy-95 commented Jul 26, 2022

Note: I've attempted to use the adafruit_hid.keyboard.Keyboard class included with the Adafruit library, but it did not allow for more than 6 keypresses without raising a ValueError instead of sending the "Rollover Error" report.

I'll work on a fork of the Adafruit HID library that implements this feature optionally.

Edit (16/11/22): Just checked the git repo for the adafruit_hid library and it looks like the code for raising a ValueError has been replaced code that overwrites the last value of the report array with a new pressed key. Not quite the behavior that I need but I'll try it out in the future to see how it goes.

@dismas666
Copy link

hi wulf. i hope you are having a great day!
I got my hands on a pico w a couple of days ago, I was already done with the first half of the keyboard and am hesitant to use the normal pico or pico w.
I was wondering if the code can be adapted to send keystrokes by bluetooth instead of the wired usbhid. I am really terrible at writing codes but for soldering I am your guy :D

thanks in advance and peace from TR!

@wulfboy-95
Copy link
Author

wulfboy-95 commented Sep 10, 2022

Hi @dismas666, the Pico W is not available in my country yet but I'll definitely try out writing a wireless version when I can get my hands on one.

In the meantime, I've started working on an app that can generate keypad matrices from keyboard layouts designed using KeyboardLayoutEditor. It will also include a new version of this code which would grab matrix and keys_list from a config file rather than having it hard-coded.

Edit (16/11/22): I've gotten my hands on a Pico W. Since Bluetooth has not been enabled yet, this would have to wait.

@goatshen
Copy link

Just wanted to say thank you Wulfboy for the updated code. I had some weird issues where i would press once but triggered twice.

I documented my experience here: https://shenmakes.blogspot.com/2022/04/sick-68-with-raspberry-pico.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment