# The Knob # Made by: Jens Ståhl # Board: RP2040-Zero # v1.0: 2025-01-12 (Initial release) #SW: GP29 #DT: GP28 #CLK: GP27 import board import time import neopixel import usb_hid import digitalio import rotaryio from adafruit_debouncer import Button from adafruit_hid.keyboard import Keyboard from adafruit_hid.keycode import Keycode from adafruit_hid.consumer_control import ConsumerControl from adafruit_hid.consumer_control_code import ConsumerControlCode pixel = neopixel.NeoPixel(board.NEOPIXEL, 1) kbd = Keyboard(usb_hid.devices) cc = ConsumerControl(usb_hid.devices) pin = digitalio.DigitalInOut(board.GP29) pin.direction = digitalio.Direction.INPUT pin.pull = digitalio.Pull.UP switch = Button(pin) encoder = rotaryio.IncrementalEncoder(board.GP27, board.GP28) last_position = 0 leftRotary, rightRotary, buttonStatus = False, False, False now = time.monotonic() lastButton = time.monotonic() lastTurn = time.monotonic() RED = (255, 0, 0) YELLOW = (255, 150, 0) GREEN = (0, 255, 0) CYAN = (0, 255, 255) BLUE = (0, 0, 255) PURPLE = (180, 0, 255) ORANGE = (220, 88, 42) BLANK = (0, 0, 0) def setLED(color): global now pixel[0] = color if color != BLANK: now = time.monotonic() while True: position = encoder.position if position > last_position: lastTurn = time.monotonic() if buttonStatus and not rightRotary: cc.send(ConsumerControlCode.SCAN_NEXT_TRACK) setLED(YELLOW) leftRotary, rightRotary = False, True elif not buttonStatus and ((lastButton + 1) < time.monotonic()): cc.send(ConsumerControlCode.VOLUME_INCREMENT) setLED(GREEN) if position < last_position: lastTurn = time.monotonic() if buttonStatus and not leftRotary: cc.send(ConsumerControlCode.SCAN_PREVIOUS_TRACK) setLED(YELLOW) leftRotary, rightRotary = True, False elif not buttonStatus and ((lastButton + 1) < time.monotonic()): cc.send(ConsumerControlCode.VOLUME_DECREMENT) setLED(BLUE) last_position = position switch.update() if switch.long_press and ((lastTurn + 1) < time.monotonic()): cc.send(ConsumerControlCode.MUTE) setLED(RED) if switch.short_count == 1 and ((lastTurn + 1) < time.monotonic()): cc.send(ConsumerControlCode.PLAY_PAUSE) setLED(CYAN) if switch.short_count == 2 and ((lastTurn + 1) < time.monotonic()): kbd.send(Keycode.ALT, Keycode.A) #Mute Zoom kbd.send(Keycode.CONTROL, Keycode.SHIFT, Keycode.M) #Mute Teams setLED(RED) if switch.pressed: buttonStatus = True if switch.released: lastButton = time.monotonic() leftRotary, rightRotary, buttonStatus = False, False, False if (time.monotonic() - now > 0.3) and not (pixel[0] == BLANK): setLED(BLANK)