aboutsummaryrefslogtreecommitdiff
path: root/src/pico/gamepad.py
diff options
context:
space:
mode:
authorZoltan Szabatin <[email protected]>2025-03-05 20:07:54 -0800
committerZoltan Szabatin <[email protected]>2025-03-05 20:07:54 -0800
commit513235a9953648026aba927d96b93b0e80b84083 (patch)
tree3f37eaf9ed4fc8257f148def2f928de93f4d046f /src/pico/gamepad.py
parentfix(Input): Controller button indexes (diff)
downloadsplitscreen-duo-513235a9953648026aba927d96b93b0e80b84083.tar.xz
splitscreen-duo-513235a9953648026aba927d96b93b0e80b84083.zip
feat: Add Pico-specific modules
Diffstat (limited to 'src/pico/gamepad.py')
-rwxr-xr-xsrc/pico/gamepad.py96
1 files changed, 96 insertions, 0 deletions
diff --git a/src/pico/gamepad.py b/src/pico/gamepad.py
new file mode 100755
index 0000000..c6d217e
--- /dev/null
+++ b/src/pico/gamepad.py
@@ -0,0 +1,96 @@
+import struct
+import time
+import board
+import digitalio
+import analogio
+from adafruit_hid import find_device
+
+class Gamepad:
+ def __init__(self, devices):
+ self._gamepad_device = find_device(devices, usage_page=0x1, usage=0x05)
+
+ self._buttons = {
+ 1: digitalio.DigitalInOut(board.GP0),
+ 2: digitalio.DigitalInOut(board.GP1),
+ 3: digitalio.DigitalInOut(board.GP2),
+ 4: digitalio.DigitalInOut(board.GP3),
+ 5: digitalio.DigitalInOut(board.GP4),
+ 6: digitalio.DigitalInOut(board.GP5),
+ 7: digitalio.DigitalInOut(board.GP6),
+ }
+
+ for button in self._buttons.values():
+ button.direction = digitalio.Direction.INPUT
+ button.pull = digitalio.Pull.UP
+
+ self._joy_x_axis = analogio.AnalogIn(board.GP26)
+ self._joy_y_axis = analogio.AnalogIn(board.GP27)
+
+ self._report = bytearray(6)
+ self._last_report = bytearray(6)
+
+ self._buttons_state = 0
+ self._joy_x = 0
+ self._joy_y = 0
+ self._joy_z = 0
+ self._joy_r_z = 0
+
+ try:
+ self.reset_all()
+ except OSError:
+ time.sleep(1)
+ self.reset_all()
+
+ def read_buttons(self):
+ self._buttons_state = 0
+ for button_num, button in self._buttons.items():
+ if not button.value:
+ self._buttons_state |= 1 << (button_num - 1)
+
+ def read_joysticks(self):
+ self._joy_x = self._scale_joystick_value(self._joy_x_axis.value)
+ self._joy_y = self._scale_joystick_value(self._joy_y_axis.value)
+
+ def _scale_joystick_value(self, value):
+ return (value - 32768) // 258
+
+ def update(self):
+ self.read_buttons()
+ self.read_joysticks()
+ self._send()
+
+ def _send(self, always=False):
+ struct.pack_into(
+ "<Hbbbb",
+ self._report,
+ 0,
+ self._buttons_state,
+ self._joy_x,
+ self._joy_y,
+ self._joy_z,
+ self._joy_r_z,
+ )
+
+ if always or self._last_report != self._report:
+ self._gamepad_device.send_report(self._report)
+ self._last_report[:] = self._report
+
+ def reset_all(self):
+ self._buttons_state = 0
+ self._joy_x = 0
+ self._joy_y = 0
+ self._joy_z = 0
+ self._joy_r_z = 0
+ self._send(always=True)
+
+ @staticmethod
+ def _validate_button_number(button):
+ if not 1 <= button <= 16:
+ raise ValueError("Button number must in range 1 to 16")
+ return button
+
+ @staticmethod
+ def _validate_joystick_value(value):
+ if not -127 <= value <= 127:
+ raise ValueError("Joystick value must be in range -127 to 127")
+ return value \ No newline at end of file