Skip to content

Commit 2f8e751

Browse files
committed
Refactor for USB mouse library and new core USB errors
1 parent e7cb145 commit 2f8e751

File tree

1 file changed

+54
-86
lines changed
  • Metro/Metro_RP2350_Minesweeper

1 file changed

+54
-86
lines changed

Metro/Metro_RP2350_Minesweeper/code.py

Lines changed: 54 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from eventbutton import EventButton
1818
import supervisor
1919
import terminalio
20-
import usb.core
20+
from adafruit_usb_host_mouse import find_and_init_boot_mouse
2121
from gamelogic import GameLogic, BLANK, INFO_BAR_HEIGHT, DIFFICULTIES
2222
from menu import Menu, SubMenu
2323

@@ -117,62 +117,14 @@ def update_ui():
117117
elapsed_time_label.text = f"Time: {game_logic.elapsed_time}"
118118

119119
# variable for the mouse USB device instance
120-
mouse = None
121-
122-
# wait a second for USB devices to be ready
123-
time.sleep(1)
124-
125-
good_devices = False
126-
wait_time = time.monotonic() + 10 # wait up to 20 seconds for a good device to be found
127-
while not good_devices and time.monotonic() < wait_time:
128-
for device in usb.core.find(find_all=True):
129-
if device.manufacturer is not None:
130-
good_devices = True
131-
break
132-
# scan for connected USB devices
133-
for device in usb.core.find(find_all=True):
134-
# print information about the found devices
135-
print(f"{device.idVendor:04x}:{device.idProduct:04x}")
136-
print(device.manufacturer, device.product)
137-
print(device.serial_number)
138-
139-
mouse_intfc,mouse_endpt = adafruit_usb_host_descriptors.find_boot_mouse_endpoint(device)
140-
if (mouse_intfc is None or mouse_endpt is None):
141-
continue # Not a mouse device
142-
143-
# assume this device is the mouse
144-
mouse = device
145-
146-
# detach from kernel driver if active
147-
if mouse.is_kernel_driver_active(mouse_intfc):
148-
mouse.detach_kernel_driver(mouse_intfc)
149-
150-
# set the mouse configuration so it can be used
151-
mouse.set_configuration()
152-
153-
# Verify mouse works by reading from it
154-
buf = array.array("b", [0] * 4)
155-
try:
156-
# Try to read some data with a short timeout
157-
data = mouse.read(mouse_endpt, buf, timeout=100)
158-
print(f"Mouse test read successful: {data} bytes - {buf}")
159-
break
160-
except usb.core.USBTimeoutError:
161-
# Timeout is normal if mouse isn't moving
162-
print("Mouse connected but not sending data (normal)")
163-
break
164-
except Exception as e: # pylint: disable=broad-except
165-
print(f"Mouse test read failed: {e}")
166-
# Continue to try next device or retry
167-
mouse = None
168-
120+
mouse = find_and_init_boot_mouse()
169121
if mouse is None:
170122
raise RuntimeError("No mouse found. Please connect a USB mouse.")
171123

172124
buf = array.array("b", [0] * 4)
173125
waiting_for_release = False
174126
left_button = right_button = False
175-
mouse_coords = (0, 0)
127+
mouse_coords = (display.width // 2, display.height // 2)
176128

177129
# Create the UI Elements (Ideally fit into 320x16 area)
178130
# Label for the Mines Left (Left of Center)
@@ -279,45 +231,61 @@ def hide_group(group):
279231

280232
menus = (reset_menu, difficulty_menu)
281233

234+
# Mouse state
235+
last_left_button_state = 0
236+
last_right_button_state = 0
237+
left_button_pressed = False
238+
right_button_pressed = False
239+
240+
# Mouse resolution/sensitivity
241+
sensitivity = 4
242+
mouse.x = mouse_coords[0] * sensitivity
243+
mouse.y = mouse_coords[1] * sensitivity
244+
245+
# Change the mouse resolution so it's not too sensitive
246+
mouse.display_size = (display.width*sensitivity, display.height*sensitivity)
247+
282248
# main loop
283249
while True:
284250
update_ui()
285251
# attempt mouse read
286-
try:
287-
# try to read data from the mouse, small timeout so the code will move on
288-
# quickly if there is no data
289-
while True:
290-
try:
291-
# read data from the mouse endpoint
292-
data_len = mouse.read(mouse_endpt, buf, timeout=10)
293-
if data_len > 0:
294-
break
295-
except usb.core.USBTimeoutError:
296-
# if we get a timeout error, it means there is no data available
297-
pass
298-
except usb.core.USBError as exc:
299-
# if we get a USBError, We may be getting no endpoint msgs which can be waited out
300-
pass
301-
302-
left_button = buf[0] & 0x01
303-
right_button = buf[0] & 0x02
304-
305-
# if there was data, then update the mouse cursor on the display
306-
# using min and max to keep it within the bounds of the display
307-
mouse_tg.x = max(0, min(display.width - 1, mouse_tg.x + buf[1] // 2))
308-
mouse_tg.y = max(0, min(display.height - 1, mouse_tg.y + buf[2] // 2))
309-
mouse_coords = (mouse_tg.x, mouse_tg.y)
310-
311-
if waiting_for_release and not left_button and not right_button:
312-
# If both buttons are released, we can process the next click
313-
waiting_for_release = False
314-
315-
# timeout error is raised if no data was read within the allotted timeout
316-
except usb.core.USBTimeoutError:
317-
# no problem, just go on
318-
pass
319-
except AttributeError as exc:
320-
raise RuntimeError("Mouse not found") from exc
252+
buttons = mouse.update()
253+
254+
# Extract button states
255+
if buttons is None:
256+
left_button = 0
257+
right_button = 0
258+
else:
259+
print(buttons)
260+
left_button = 1 if 'left' in buttons else 0
261+
right_button = 1 if 'right' in buttons else 0
262+
263+
# Detect button presses
264+
if left_button == 1 and last_left_button_state == 0:
265+
left_button_pressed = True
266+
elif left_button == 0 and last_left_button_state == 1:
267+
left_button_pressed = False
268+
269+
if right_button == 1 and last_right_button_state == 0:
270+
right_button_pressed = True
271+
elif right_button == 0 and last_right_button_state == 1:
272+
right_button_pressed = False
273+
274+
# Update button states
275+
last_left_button_state = left_button
276+
last_right_button_state = right_button
277+
278+
# Update position
279+
# Ensure position stays within bounds
280+
mouse_tg.x = max(0, min(display.width - 1, mouse.x // sensitivity))
281+
mouse_tg.y = max(0, min(display.height - 1, mouse.y // sensitivity))
282+
283+
mouse_coords = (mouse_tg.x, mouse_tg.y)
284+
285+
if waiting_for_release and not left_button and not right_button:
286+
# If both buttons are released, we can process the next click
287+
waiting_for_release = False
288+
321289
if not message_dialog.hidden:
322290
if message_button.handle_mouse(mouse_coords, left_button, waiting_for_release):
323291
waiting_for_release = True

0 commit comments

Comments
 (0)