Skip to content

Commit cebb149

Browse files
committed
Updated lib and added gamepad icon
ensured the gamepad state is set correctly
1 parent bef7ec1 commit cebb149

File tree

14 files changed

+174
-16
lines changed

14 files changed

+174
-16
lines changed
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"}}}}}}}}]}}

public/lib/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+

public/lib/XRPLib/imu.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from .imu_defs import *
88
from uctypes import struct, addressof
99
except (TypeError, ModuleNotFoundError):
10+
LSM_ADDR_PRIMARY = 0x6A
1011
# Import wrapped in a try/except so that autodoc generation can process properly
1112
pass
1213
from machine import I2C, Pin, Timer, disable_irq, enable_irq

public/lib/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+

public/lib/XRPLib/timeout.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,23 @@
11
import time
22

33
class Timeout:
4-
def __init__(self, timeout):
4+
def __init__(self, timeout: float):
55
"""
66
Starts a timer that will expire after the given timeout.
77
88
:param timeout: The timeout, in seconds
99
:type timeout: float
1010
"""
1111
self.timeout = timeout
12-
self.start_time = time.time()
12+
if self.timeout != None:
13+
self.timeout = timeout*1000
14+
15+
self.start_time = time.ticks_ms()
1316

1417
def is_done(self):
1518
"""
1619
:return: True if the timeout has expired, False otherwise
1720
"""
1821
if self.timeout is None:
1922
return False
20-
return time.time() - self.start_time > self.timeout
23+
return time.ticks_ms() - self.start_time > self.timeout

public/lib/ble/ble_uart_peripheral.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#from .ble_advertising import advertising_payload
55
import struct
66
from micropython import const
7+
from machine import Timer
78

89
#Advertise info
910
# org.bluetooth.characteristic.gap.appearance.xml
@@ -47,6 +48,12 @@
4748
(_UART_TX, _UART_RX, _UART_DATA_RX, _UART_DATA_TX,),
4849
)
4950

51+
_timer = Timer(-1)
52+
53+
def delayedRestart(_arg):
54+
import machine
55+
machine.reset()
56+
5057
class BLEUART:
5158
def __init__(self, ble, name="mpy-uart", rxbuf=100):
5259
self._ble = ble
@@ -82,8 +89,12 @@ def _irq(self, event, data):
8289
self._rx_buffer += self._ble.gatts_read(self._rx_handle)
8390
if(self._rx_buffer.find(b'##XRPSTOP#' + b'#') != -1): #WARNING: This is broken up so it won't restart during an update or this file.
8491
self._rx_buffer = bytearray()
85-
import machine
86-
machine.reset()
92+
# set the bit in isrunning to tell main not to re-run the program so the IDE can connect
93+
FILE_PATH = '/lib/ble/isrunning'
94+
with open(FILE_PATH, 'r+b') as file:
95+
file.write(b'\x01')
96+
# slight delay to avoid errors on the browser side.
97+
_timer.init(mode=Timer.PERIODIC, period=50, callback=delayedRestart)
8798
elif conn_handle in self._connections and value_handle == self._data_rx_handle:
8899
new_data = self._ble.gatts_read(self._data_rx_handle)
89100
if self._data_callback:
@@ -92,8 +103,8 @@ def _irq(self, event, data):
92103
elif event == _IRQ_GATTS_INDICATE_DONE:
93104
if self._handler:
94105
self._handler()
95-
else:
96-
print("IRQ Event Code: " + str(event))
106+
#else:
107+
#print("IRQ Event Code: " + str(event))
97108

98109
def any(self):
99110
return len(self._rx_buffer)

public/lib/package.json

Lines changed: 4 additions & 2 deletions
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,13 +21,14 @@
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"],
24-
["XRPExamples/led_example.py", "github:Open-STEM/XRP_Micropython/XRPExamples/misc_examples.py"],
26+
["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"],
2628
["XRPExamples/webserver_example.py", "github:Open-STEM/XRP_Micropython/XRPExamples/webserver_example.py"]
2729
],
2830
"deps": [
2931
["github:pimoroni/phew", "latest"]
3032
],
31-
"version": "2.0.1"
33+
"version": "2.1.3"
3234
}

public/plugins/sample_plugin.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22
"plugins": [
33
{
44
"friendly_name": "Advanced Sensors",
5-
"blocks_url": "/public/plugins/advanced_sensors/blocks.json",
6-
"script_url": "/public/plugins/advanced_sensors/blocks.js"
5+
"blocks_url": "/plugins/advanced_sensors/blocks.json",
6+
"script_url": "/plugins/advanced_sensors/blocks.js"
77
},
88
{
99
"friendly_name": "Custom Motors",
10-
"blocks_url": "/public/plugins/custom_motors/blocks.json",
11-
"script_url": "/public/plugins/custom_motors/blocks.js"
10+
"blocks_url": "/plugins/custom_motors/blocks.json",
11+
"script_url": "/plugins/custom_motors/blocks.js"
1212
}
1313
]
1414
}

src/assets/images/gamepad.png

-45.8 KB
Binary file not shown.

src/assets/images/gamepad.svg

Lines changed: 1 addition & 0 deletions
Loading

0 commit comments

Comments
 (0)