import usb_hid import supervisor import storage import usb_midi DEFAULT_REPORT_ID = 1 HANDSHAKE_REPORT_ID = 2 VENDOR_ID = 0x0359 PRODUCT_ID = 0x6497 # T9 MIXR RESOLUTION = 100 # Voicemeeter sliders go from 12.0 to -60.0 in 0.1 increments REPORT_DESCRIPTOR = bytes([ 0x05, 0x01, # Usage Page (Generic Desktop Controls) 0x09, 0x08, # Usage (Multi-Axis Controller) #0x09, 0x04, # Joystick usage (for windows to pick up as usb controller) 0xA1, 0x01, # Collection (Application) # BUTTONS 0x05, 0x09, # Usage Page (Button) 0x19, 0x01, # Usage Minimum (Button 1) 0x29, 0x30, # Usage Maximum (Button 48) 0x15, 0x00, # Logical Minimum (0) 0x25, 0x01, # Logical Maximum (1) 0x75, 0x01, # Report Size (1 bit) 0x95, 0x30, # Report Count (48) 0x81, 0x02, # Input (Data, Variable, Absolute) # SLIDERS 0x15, 0x00, # Logical Minimum (0) 0x26, 0xFF, 0xFF, # Logical Maximum (RESOLUTION (720)) 0x75, 0x10, # Report Size (16-bit) #0x85, DEFAULT_REPORT_ID, # Report ID (DEFAULT_REPORT_ID) 0x95, 0x05, # Report Count (5) 0x09, 0x30, # Usage (X) 0x09, 0x31, # Usage (Y) 0x09, 0x32, # Usage (Z) 0x09, 0x33, # Usage (Rx) 0x09, 0x34, # Usage (Ry) 0x81, 0x00, # Input (Data, Array, Absolute) 0xC0, # End Collection #0x05, 0x06, # Usage Page (Generic Device Controls) #0x09, 0x01, # Usage (Background/Nonuser controls) #0xA1, 0x01, # Collection (Application) #0x75, 0x20, # Report Size (32-bit) #0x95, 0x01, # Report Count (1) #0x85, HANDSHAKE_REPORT_ID,# Report ID (HANDSHAKE_REPORT_ID) #0x81, 0x01, # Input (Constant, Array, Absolute) #0xC0, # End Collection ]) def initUsb(): if supervisor.runtime.usb_connected: raise RuntimeError("USB cannot be initialized post-boot") supervisor.set_usb_identification(manufacturer="TechAbsol", product="USB Mixer", vid=VENDOR_ID, pid=PRODUCT_ID) usb_midi.disable() usb_hid.set_interface_name("CircuitPython Mixer") sliders = usb_hid.Device( report_descriptor = REPORT_DESCRIPTOR, usage_page=0x01, usage=0x08, report_ids=(0,), in_report_lengths=(16,), out_report_lengths=(0,), ) #storage.disable_usb_drive() #storage.remount("/", False) usb_hid.enable((sliders,)) class UsbMixer(): def __init__(self): if not supervisor.runtime.usb_connected: raise RuntimeError("USB is not connected") self._device = next((dev for dev in usb_hid.devices if dev.usage_page == 0x01 and dev.usage == 0x08)) if self._device is None: raise RuntimeError("USB mixer doesn't appear to be initialized") def _valToBytes(self, value): return bytes([value & 0xFF, (value >> 8) & 0xFF]) def _keysToBytes(self, keys): return bytes([keys[0], keys[1], keys[2], keys[3], keys[4], keys[5]]) def send_values(self, slider1, slider2, slider3, slider4, slider5, keys): report = self._keysToBytes(keys) + self._valToBytes(slider1) + self._valToBytes(slider2) + self._valToBytes(slider3) + self._valToBytes(slider4) + self._valToBytes(slider5) self._device.send_report(report)