Back to Posts

Macropad: V2 Software and Hardware Improvements

Quick follow up to my previous post where I built my first macropad using a Waveshare RP2040-Zero and 3D printed parts just so I could run around while punching in codes while gaming with friends.

V2 of code.py and boot.py bring improvements and I redesigned my case to make room for the MCU to be flipped to make it easier to access the RESET and BOOT buttons.

If you are starting fresh, you will need to download:

Updated code file based on the Adafruit examples and the previous code I used.

# code.py
import time
import board
import digitalio
import usb_hid

from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS
from adafruit_hid.keycode import Keycode

# Update board pins based on your MCU. Not all use GP* naming.
keypress_pins = [board.GP3, board.GP4, board.GP5, board.GP6]
# keycode to send when the index is called
keys_pressed = [Keycode.UP_ARROW, Keycode.DOWN_ARROW, Keycode.LEFT_ARROW, Keycode.RIGHT_ARROW]
# Our array of key objects
key_pin_array = []

time.sleep(1)  # Sleep for a bit to avoid a race condition on some systems

# Keyboard object for sending values
keyboard = Keyboard(usb_hid.devices)
keyboard_layout = KeyboardLayoutUS(keyboard)

# Use Pull Down for input
for pin in keypress_pins:
    key_pin = digitalio.DigitalInOut(pin)
    key_pin.direction = digitalio.Direction.INPUT
    key_pin.pull = digitalio.Pull.DOWN
    key_pin_array.append(key_pin)

key_states = [False] * len(key_pin_array)

def check_keypress(index):
    # Check if button is pressed
    if key_pin_array[index].value and not btn_states[index]:
        keycode = keys_pressed[index]
        keyboard.send(keycode)
        key_states[index] = True  # Mark as pressed
        # time.sleep(0.2)  # Debounce delay
    elif not key_pin_array[index].value and btn_states[index]:
        key_states[index] = False  # Reset state on release


while True:
    for index, key_pin in enumerate(key_pin_array):
        check_keypress(index)

    # Reduce sleep to make loop more responsive but still avoid too fast polling
    time.sleep(0.01)

The boot file was tested to get the correct configuration and add a way to re-enable storage mode if needed for additional work.

# boot.py
import storage
import board, digitalio

key_pin = digitalio.DigitalInOut(board.GP3)
key_pin.direction = digitalio.Direction.INPUT
key_pin.pull = digitalio.Pull.DOWN

if key_pin.value is False:
    storage.disable_usb_drive()

print(f'Storage mode: {key_pin.value}')

Conclusion

With these changes, the macropad is easier to use and service. I will report back after I've used it a bit and get some laser cut feet for it. In the mean time, I'm off to collect more super samples.

© 2024