pastebin - collaborative debugging tool
circuitpython.kpaste.net RSS


WorkingJoystickExample Circuitpython 6.x.x
Posted by Anonymous on Mon 7th Jun 2021 01:47
raw | new post

  1. import board
  2. import digitalio
  3. import time
  4.  
  5. # SPDX-FileCopyrightText: 2018 Dan Halbert for Adafruit Industries
  6. #
  7. # SPDX-License-Identifier: MIT
  8.  
  9. """
  10. `Gamepad`
  11. ====================================================
  12.  
  13. * Author(s): Dan Halbert
  14. """
  15.  
  16. import struct
  17. import time
  18.  
  19. import usb_hid
  20.  
  21. from adafruit_hid import find_device
  22.  
  23.  
  24. class Gamepad:
  25.     """Emulate a generic gamepad controller with 16 buttons,
  26.    numbered 1-16, and two joysticks, one controlling
  27.    ``x` and ``y`` values, and the other controlling ``z`` and
  28.    ``r_z`` (z rotation or ``Rz``) values.
  29.  
  30.    The joystick values could be interpreted
  31.    differently by the receiving program: those are just the names used here.
  32.    The joystick values are in the range -127 to 127."""
  33.  
  34.     def __init__(self, devices):
  35.         """Create a Gamepad object that will send USB gamepad HID reports.
  36.  
  37.        Devices can be a list of devices that includes a gamepad device or a gamepad device
  38.        itself. A device is any object that implements ``send_report()``, ``usage_page`` and
  39.        ``usage``.
  40.        """
  41.         self._gamepad_device = find_device(devices, usage_page=0x1, usage=0x05)
  42.  
  43.         # Reuse this bytearray to send mouse reports.
  44.         # Typically controllers start numbering buttons at 1 rather than 0.
  45.         # report[0] buttons 1-8 (LSB is button 1)
  46.         # report[1] buttons 9-16
  47.         # report[2] joystick 0 x: -127 to 127
  48.         # report[3] joystick 0 y: -127 to 127
  49.         # report[4] joystick 1 x: -127 to 127
  50.         # report[5] joystick 1 y: -127 to 127
  51.         self._report = bytearray(6)
  52.  
  53.         # Remember the last report as well, so we can avoid sending
  54.         # duplicate reports.
  55.         self._last_report = bytearray(6)
  56.  
  57.         # Store settings separately before putting into report. Saves code
  58.         # especially for buttons.
  59.         self._buttons_state = 0
  60.         self._joy_x = 0
  61.         self._joy_y = 0
  62.         self._joy_z = 0
  63.         self._joy_r_z = 0
  64.  
  65.         # Send an initial report to test if HID device is ready.
  66.         # If not, wait a bit and try once more.
  67.         try:
  68.             self.reset_all()
  69.         except OSError:
  70.             time.sleep(1)
  71.             self.reset_all()
  72.  
  73.     def press_buttons(self, *buttons):
  74.         """Press and hold the given buttons. """
  75.         for button in buttons:
  76.             self._buttons_state |= 1 << self._validate_button_number(button) - 1
  77.         self._send()
  78.  
  79.     def release_buttons(self, *buttons):
  80.         """Release the given buttons. """
  81.         for button in buttons:
  82.             self._buttons_state &= ~(1 << self._validate_button_number(button) - 1)
  83.         self._send()
  84.  
  85.     def release_all_buttons(self):
  86.         """Release all the buttons."""
  87.  
  88.         self._buttons_state = 0
  89.         self._send()
  90.  
  91.     def click_buttons(self, *buttons):
  92.         """Press and release the given buttons."""
  93.         self.press_buttons(*buttons)
  94.         self.release_buttons(*buttons)
  95.  
  96.     def move_joysticks(self, x=None, y=None, z=None, r_z=None):
  97.         """Set and send the given joystick values.
  98.        The joysticks will remain set with the given values until changed
  99.  
  100.        One joystick provides ``x`` and ``y`` values,
  101.        and the other provides ``z`` and ``r_z`` (z rotation).
  102.        Any values left as ``None`` will not be changed.
  103.  
  104.        All values must be in the range -127 to 127 inclusive.
  105.  
  106.        Examples::
  107.  
  108.            # Change x and y values only.
  109.            gp.move_joysticks(x=100, y=-50)
  110.  
  111.            # Reset all joystick values to center position.
  112.            gp.move_joysticks(0, 0, 0, 0)
  113.        """
  114.         if x is not None:
  115.             self._joy_x = self._validate_joystick_value(x)
  116.         if y is not None:
  117.             self._joy_y = self._validate_joystick_value(y)
  118.         if z is not None:
  119.             self._joy_z = self._validate_joystick_value(z)
  120.         if r_z is not None:
  121.             self._joy_r_z = self._validate_joystick_value(r_z)
  122.         self._send()
  123.  
  124.     def reset_all(self):
  125.         """Release all buttons and set joysticks to zero."""
  126.         self._buttons_state = 0
  127.         self._joy_x = 0
  128.         self._joy_y = 0
  129.         self._joy_z = 0
  130.         self._joy_r_z = 0
  131.         self._send(always=True)
  132.  
  133.     def _send(self, always=False):
  134.         """Send a report with all the existing settings.
  135.        If ``always`` is ``False`` (the default), send only if there have been changes.
  136.        """
  137.         struct.pack_into(
  138.             "<Hbbbb",
  139.             self._report,
  140.             0,
  141.             self._buttons_state,
  142.             self._joy_x,
  143.             self._joy_y,
  144.             self._joy_z,
  145.             self._joy_r_z,
  146.         )
  147.  
  148.         if always or self._last_report != self._report:
  149.             self._gamepad_device.send_report(self._report)
  150.             # Remember what we sent, without allocating new storage.
  151.             self._last_report[:] = self._report
  152.  
  153.     @staticmethod
  154.     def _validate_button_number(button):
  155.         if not 1 <= button <= 16:
  156.             raise ValueError("Button number must in range 1 to 16")
  157.         return button
  158.  
  159.     @staticmethod
  160.     def _validate_joystick_value(value):
  161.         if not -127 <= value <= 127:
  162.             raise ValueError("Joystick value must be in range -127 to 127")
  163.         return value
  164.  
  165.  
  166.  
  167. gp = Gamepad(usb_hid.devices)
  168.  
  169. def range_map(x, in_min, in_max, out_min, out_max):
  170.     return (x - in_min) * (out_max - out_min) // (in_max - in_min) + out_min
  171.  
  172. print("gamepad for circuitpython 6.xxx")
  173.  
  174.  
  175. oldX=-127
  176. oldY=-127
  177.  
  178.  
  179. while True:
  180.     # Buttons are grounded when pressed (.value = False).
  181.     oldX = oldX + 1
  182.     if (oldX > 127):
  183.         oldX = -127
  184.     oldY = oldY + 1
  185.     if (oldY > 127):
  186.         oldY = -127
  187.     gp.move_joysticks(
  188.         x=oldX,
  189.         y=oldY,
  190.         z=oldX,
  191.         r_z=oldY
  192.     )
  193.     print(" x", oldX, "y", oldY)
  194.     time.sleep(0.01)

Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:

To highlight particular lines, prefix each line with {%HIGHLIGHT}




All content is user-submitted.
The administrators of this site (kpaste.net) are not responsible for their content.
Abuse reports should be emailed to us at