|
17 | 17 | from eventbutton import EventButton |
18 | 18 | import supervisor |
19 | 19 | import terminalio |
20 | | -import usb.core |
| 20 | +from adafruit_usb_host_mouse import find_and_init_boot_mouse |
21 | 21 | from gamelogic import GameLogic, BLANK, INFO_BAR_HEIGHT, DIFFICULTIES |
22 | 22 | from menu import Menu, SubMenu |
23 | 23 |
|
@@ -117,62 +117,14 @@ def update_ui(): |
117 | 117 | elapsed_time_label.text = f"Time: {game_logic.elapsed_time}" |
118 | 118 |
|
119 | 119 | # 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() |
169 | 121 | if mouse is None: |
170 | 122 | raise RuntimeError("No mouse found. Please connect a USB mouse.") |
171 | 123 |
|
172 | 124 | buf = array.array("b", [0] * 4) |
173 | 125 | waiting_for_release = False |
174 | 126 | left_button = right_button = False |
175 | | -mouse_coords = (0, 0) |
| 127 | +mouse_coords = (display.width // 2, display.height // 2) |
176 | 128 |
|
177 | 129 | # Create the UI Elements (Ideally fit into 320x16 area) |
178 | 130 | # Label for the Mines Left (Left of Center) |
@@ -279,45 +231,61 @@ def hide_group(group): |
279 | 231 |
|
280 | 232 | menus = (reset_menu, difficulty_menu) |
281 | 233 |
|
| 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 | + |
282 | 248 | # main loop |
283 | 249 | while True: |
284 | 250 | update_ui() |
285 | 251 | # 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 | + |
321 | 289 | if not message_dialog.hidden: |
322 | 290 | if message_button.handle_mouse(mouse_coords, left_button, waiting_for_release): |
323 | 291 | waiting_for_release = True |
|
0 commit comments