Skip to content

Commit db78fac

Browse files
authored
Merge pull request #86 from Open-STEM/frank
Add in Gamepad support
2 parents 9b4e830 + c045240 commit db78fac

File tree

4 files changed

+125
-1
lines changed

4 files changed

+125
-1
lines changed

XRPExamples/gamepad_example.blocks

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from XRPLib.gamepad import *
2+
from XRPLib.differential_drive import DifferentialDrive
3+
4+
gp = Gamepad.get_default_gamepad()
5+
6+
differentialDrive = DifferentialDrive.get_default_differential_drive()
7+
8+
9+
while not (gp.is_button_pressed(gp.BACK)):
10+
differentialDrive.arcade((gp.get_value(gp.Y1)), (gp.get_value(gp.X1)))
11+
12+
13+
14+
## [2025-07-13 01:36:24]
15+
##XRPBLOCKS {"blocks":{"languageVersion":0,"blocks":[{"type":"controls_whileUntil","id":"#/DDnbE2JxVsLQo`C`e^","x":-363,"y":16,"fields":{"MODE":"UNTIL"},"inputs":{"BOOL":{"block":{"type":"xrp_gp_button_pressed","id":"DtLypJc;SU2xT4A~S3nV","fields":{"GPBUTTON":"BACK"}}},"DO":{"block":{"type":"xrp_arcade","id":"(|]Iln#JYa9hzgEz+(4g","inputs":{"STRAIGHT":{"shadow":{"type":"math_number","id":"FOj1uvC$:~x/+cX}d(:|","fields":{"NUM":0.8}},"block":{"type":"xrp_gp_get_value","id":"s#GS_Dt)B8Cb9+4ctpwk","fields":{"GPVALUE":"Y1"}}},"TURN":{"shadow":{"type":"math_number","id":"n1jAKrjST!+3#bfChh$d","fields":{"NUM":0.2}},"block":{"type":"xrp_gp_get_value","id":"*]`U9XHyYnA?Gp%U;$NF","fields":{"GPVALUE":"X1"}}}}}}}}]}}

XRPLib/gamepad.py

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
from ble.blerepl import uart
2+
import sys
3+
from micropython import const
4+
5+
class Gamepad:
6+
7+
_DEFAULT_GAMEPAD_INSTANCE = None
8+
9+
X1 = const(0)
10+
Y1 = const(1)
11+
X2 = const(2)
12+
Y2 = const(3)
13+
BUTTON_A = const(4)
14+
BUTTON_B = const(5)
15+
BUTTON_X = const(6)
16+
BUTTON_Y = const(7)
17+
BUMPER_L = const(8)
18+
BUMPER_R = const(9)
19+
TRIGGER_L = const(10)
20+
TRIGGER_R = const(11)
21+
BACK = const(12)
22+
START = const(13)
23+
DPAD_UP = const(14)
24+
DPAD_DN = const(15)
25+
DPAD_L = const(16)
26+
DPAD_R = const(17)
27+
28+
_joyData = [
29+
0.0,
30+
0.0,
31+
0.0,
32+
0.0,
33+
0,0,0,0,0,0,0,0,0,0,0,0,0,0]
34+
35+
@classmethod
36+
def get_default_gamepad(cls):
37+
"""
38+
Get the default XRP bluetooth joystick instance. This is a singleton, so only one instance of the gamepad sensor will ever exist.
39+
"""
40+
if cls._DEFAULT_GAMEPAD_INSTANCE is None:
41+
cls._DEFAULT_GAMEPAD_INSTANCE = cls()
42+
cls._DEFAULT_GAMEPAD_INSTANCE.start()
43+
return cls._DEFAULT_GAMEPAD_INSTANCE
44+
45+
def __init__(self):
46+
"""
47+
Manages communication with gamepad data coming from a remote computer via bluetooth
48+
49+
"""
50+
def start(self):
51+
"""
52+
Signals the remote computer to begin sending gamepad data packets.
53+
"""
54+
for i in range(len(self._joyData)):
55+
self._joyData[i] = 0.0
56+
uart.set_data_callback(self._data_callback)
57+
sys.stdout.write(chr(27))
58+
sys.stdout.write(chr(101))
59+
60+
61+
def stop(self):
62+
"""
63+
Signals the remote computer to stop sending gamepad data packets.
64+
"""
65+
sys.stdout.write(chr(27))
66+
sys.stdout.write(chr(102))
67+
68+
def get_value(self, index:int) -> float:
69+
"""
70+
Get the current value of a joystick axis
71+
72+
:param index: The joystick axis index
73+
Gamepad.X1, Gamepad.Y1, Gamepad.X2, Gamepad.Y2
74+
:type int
75+
:returns: The value of the joystick between -1 and 1
76+
:rtype: float
77+
"""
78+
return -self._joyData[index] #returning the negative to make normal for user
79+
80+
def is_button_pressed(self, index:int) -> bool:
81+
"""
82+
Checks if a specific button is currently pressed.
83+
84+
:param index: The button index
85+
Gamepad.BUTTON_A, Gamepad.TRIGGER_L, Gamepad.DPAD_UP, etc
86+
:type int
87+
:returns: The value of the button 1 or 0
88+
:rtype: bool
89+
"""
90+
return self._joyData[index] > 0
91+
92+
def _data_callback(self, data):
93+
if(data[0] == 0x55 and len(data) == data[1] + 2):
94+
for i in range(2, data[1] + 2, 2):
95+
self._joyData[data[i]] = round(data[i + 1]/127.5 - 1, 2)
96+
97+

XRPLib/resetbot.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,21 @@ def reset_webserver():
3333
# Shut off the webserver and close network connections
3434
Webserver.get_default_webserver().stop_server()
3535

36+
def reset_gamepad():
37+
from XRPLib.gamepad import Gamepad
38+
# Stop the browser from sending more gamepad data
39+
Gamepad.get_default_gamepad().stop()
40+
3641
def reset_hard():
42+
reset_gamepad()
3743
reset_motors()
3844
reset_led()
3945
reset_servos()
4046
reset_webserver()
4147

48+
if "XRPLib.gamepad" in sys.modules:
49+
reset_gamepad()
50+
4251
if "XRPLib.encoded_motor" in sys.modules:
4352
reset_motors()
4453

@@ -50,3 +59,4 @@ def reset_hard():
5059

5160
if "XRPLib.webserver" in sys.modules:
5261
reset_webserver()
62+

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
["XRPLib/differential_drive.py", "github:Open-STEM/XRP_Micropython/XRPLib/differential_drive.py"],
88
["XRPLib/encoded_motor.py", "github:Open-STEM/XRP_Micropython/XRPLib/encoded_motor.py"],
99
["XRPLib/encoder.py", "github:Open-STEM/XRP_Micropython/XRPLib/encoder.py"],
10+
["XRPLib/gamepad.py", "github:Open-STEM/XRP_Micropython/XRPLib/gamepad.py"],
1011
["XRPLib/imu_defs.py", "github:Open-STEM/XRP_Micropython/XRPLib/imu_defs.py"],
1112
["XRPLib/imu.py", "github:Open-STEM/XRP_Micropython/XRPLib/imu.py"],
1213
["XRPLib/motor_group.py", "github:Open-STEM/XRP_Micropython/XRPLib/motor_group.py"],
@@ -20,6 +21,7 @@
2021
["XRPLib/webserver.py", "github:Open-STEM/XRP_Micropython/XRPLib/webserver.py"],
2122
["XRPExamples/__init__.py", "github:Open-STEM/XRP_Micropython/XRPExamples/__init__.py"],
2223
["XRPExamples/drive_examples.py", "github:Open-STEM/XRP_Micropython/XRPExamples/drive_examples.py"],
24+
["XRPExamples/gamepad_example.blocks", "github:Open-STEM/XRP_Micropython/XRPExamples/gamepad_example.blocks"],
2325
["XRPExamples/installation_verification.py", "github:Open-STEM/XRP_Micropython/XRPExamples/installation_verification.py"],
2426
["XRPExamples/led_example.py", "github:Open-STEM/XRP_Micropython/XRPExamples/led_example.py"],
2527
["XRPExamples/sensor_examples.py", "github:Open-STEM/XRP_Micropython/XRPExamples/sensor_examples.py"],
@@ -28,5 +30,5 @@
2830
"deps": [
2931
["github:pimoroni/phew", "latest"]
3032
],
31-
"version": "2.0.1"
33+
"version": "2.1.3"
3234
}

0 commit comments

Comments
 (0)