Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 46 additions & 5 deletions Fruit_Jam/Fruit_Jam_PyPaint/code.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,17 @@
"""

import gc
import sys
import time
import atexit
import supervisor
import board
import displayio
import terminalio
from adafruit_display_text import label

try:
from adafruit_usb_host_mouse import find_and_init_boot_mouse
from adafruit_usb_host_mouse import find_and_init_boot_mouse, find_and_init_report_mouse
usb_available = True
except ImportError:
usb_available = False
Expand Down Expand Up @@ -208,13 +212,17 @@ def __init__(self, splash, cursor_bmp, screen_width, screen_height, sensitivity=
def find_mouse(self): # pylint: disable=too-many-statements, too-many-locals
"""Find and initialize the USB mouse."""
self.mouse = find_and_init_boot_mouse()
if self.mouse is None:
self.mouse = find_and_init_report_mouse()
self.sensitivity = 1
if self.mouse is None:
print("No mouse found.")
return False

# Change the mouse resolution so it's not too sensitive
fontHeight = terminalio.FONT.get_bounding_box()[1]
self.mouse.display_size = (supervisor.runtime.display.width*self.sensitivity,
supervisor.runtime.display.height*self.sensitivity)
(supervisor.runtime.display.height - fontHeight)*self.sensitivity)
return True

def poll(self):
Expand Down Expand Up @@ -324,12 +332,24 @@ def _cursor_bitmap_3():

self._display = display
self._w = self._display.width
self._h = self._display.height
self._h = self._display.height - terminalio.FONT.get_bounding_box()[1]
self._x = self._w // 2
self._y = self._h // 2

self._splash = displayio.Group()

self._info_label = label.Label(
terminalio.FONT,
text = "Right Click->Palette:Exit Right Click->Canvas:Fill"[:self._w],
color = 0xFFFFFF,
x = 0,
y = self._h
)
self._info_label.anchor_point = (0.0, 1.0)
self._info_label.anchored_position = (2, display.height - 2)

self._splash.append(self._info_label)

self._bg_bitmap = displayio.Bitmap(self._w, self._h, 1)
self._bg_palette = displayio.Palette(1)
self._bg_palette[0] = Color.BLACK
Expand Down Expand Up @@ -377,6 +397,7 @@ def _cursor_bitmap_3():

self._brush = 0
self._cursor_bitmaps = [_cursor_bitmap_1(), _cursor_bitmap_3()]
self.mouse = None
if hasattr(board, "TOUCH_XL"):
self._poller = TouchscreenPoller(self._splash, self._cursor_bitmaps[0])
elif hasattr(board, "BUTTON_CLOCK"):
Expand All @@ -385,8 +406,9 @@ def _cursor_bitmap_3():
self._poller = MousePoller(self._splash, self._cursor_bitmaps[0], self._w, self._h)
if not self._poller.mouse:
raise RuntimeError("No mouse found. Please connect a USB mouse.")
self.mouse = self._poller.mouse
else:
raise AttributeError("PyPaint requires a touchscreen or cursor.")
raise AttributeError("PyPaint requires a mouse, touchscreen or cursor.")

self._a_pressed = False
self._last_a_pressed = False
Expand Down Expand Up @@ -603,6 +625,8 @@ def _handle_b_release(self, location):
if location[0] >= self._w // 10: # not in color picker
self._fill(location[0], location[1], self._pencolor)
self._poller.poke()
else:
supervisor.reload()

@property
def _was_a_just_pressed(self):
Expand Down Expand Up @@ -646,6 +670,23 @@ def run(self):
self._handle_motion(self._last_location, self._location)
time.sleep(0.1)


painter = Paint()

def atexit_callback():
"""
re-attach USB devices to kernel if needed.
:return:
"""
print("inside atexit callback")
if painter.mouse is not None:
mouse = painter.mouse
if mouse.was_attached and not mouse.device.is_kernel_driver_active(0):
mouse.device.attach_kernel_driver(0)
# The keyboard buffer seems to have data left over from when it was detached
# This clears it before the next process starts
while supervisor.runtime.serial_bytes_available:
sys.stdin.read(1)

atexit.register(atexit_callback)

painter.run()
135 changes: 62 additions & 73 deletions Metro/Metro_RP2350_Memory/memory_game/code.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

Players trade off using the USB mouse to play their turns.
"""
import array
import sys
import random
import time
import atexit
Expand All @@ -18,9 +18,8 @@
from adafruit_ticks import ticks_ms
import supervisor
import terminalio
import usb.core
from adafruit_fruitjam.peripherals import request_display_config
import adafruit_usb_host_descriptors
from adafruit_usb_host_mouse import find_and_init_boot_mouse, find_and_init_report_mouse
from adafruit_pathlib import Path


Expand Down Expand Up @@ -223,6 +222,20 @@ def update_score_text():
# add the game over group to the main group
main_group.append(game_over_group)

# add the Exit Game button to game screen
exit_game = TextBox(
terminalio.FONT,
text="Exit",
color=0xFFFFFF,
background_color=0xFF0000,
width=30,
height=15,
align=TextBox.ALIGN_CENTER,
)
exit_game.x = display.width - 30
exit_game.y = display.height - 15
main_group.append(exit_game)

# create score label for each player
for i in range(2):
# create a new label to hold score
Expand Down Expand Up @@ -268,78 +281,45 @@ def update_score_text():
# add it to the main group
main_group.append(title_screen_tg)

# load the mouse bitmap
mouse_bmp = OnDiskBitmap("mouse_cursor.bmp")

# make the background pink pixels transparent
mouse_bmp.pixel_shader.make_transparent(0)

# create a TileGrid for the mouse
mouse_tg = TileGrid(mouse_bmp, pixel_shader=mouse_bmp.pixel_shader)

# place it in the center of the display
mouse_tg.x = display.width // 2
mouse_tg.y = display.height // 2

# add the mouse to the main group
main_group.append(mouse_tg)

# variable for the mouse USB device instance
mouse = None

# wait a second for USB devices to be ready
time.sleep(1)

mouse_interface_index, mouse_endpoint_address = None, None
mouse = None

# scan for connected USB devices
for device in usb.core.find(find_all=True):
# print information about the found devices
print(f"{device.idVendor:04x}:{device.idProduct:04x}")
print(device.manufacturer, device.product)
print(device.serial_number)
mouse_interface_index, mouse_endpoint_address = (
adafruit_usb_host_descriptors.find_boot_mouse_endpoint(device))

if mouse_interface_index is not None and mouse_endpoint_address is not None:
mouse = device
print(
f"mouse interface: {mouse_interface_index} "
+ f"endpoint_address: {hex(mouse_endpoint_address)}"
)

break
mouse_ptr = find_and_init_boot_mouse("mouse_cursor.bmp")
if mouse_ptr is None:
mouse_ptr = find_and_init_report_mouse("mouse_cursor.bmp")
if mouse_ptr is None:
print("No mouse found.")
mouse = mouse_ptr.device

mouse_tg = mouse_ptr.tilegrid

mouse_was_attached = None
if mouse is not None:
# detach the kernel driver if needed
if mouse.is_kernel_driver_active(0):
mouse_was_attached = True
mouse.detach_kernel_driver(0)
else:
mouse_was_attached = False
# place it in the center of the display
mouse_tg.x = display.width // 2
mouse_tg.y = display.height // 2

# set configuration on the mouse so we can use it
mouse.set_configuration()
# add the mouse to the main group
main_group.append(mouse_tg)

def atexit_callback():
"""
re-attach USB devices to kernel if needed.
:return:
"""
print("inside atexit callback")
if mouse_was_attached and not mouse.is_kernel_driver_active(0):
mouse.attach_kernel_driver(0)

if mouse is not None:
if mouse_ptr.was_attached and not mouse_ptr.device.is_kernel_driver_active(0):
mouse.attach_kernel_driver(0)
# The keyboard buffer seems to have data left over from when it was detached
# This clears it before the next process starts
while supervisor.runtime.serial_bytes_available:
sys.stdin.read(1)

atexit.register(atexit_callback)

# Buffer to hold data read from the mouse
# Boot mice have 4 byte reports
buf = array.array("b", [0] * 4)

# timestamp in the future to wait until before
# awarding points for a pair, or flipping cards
# back over and changing turns
Expand All @@ -352,36 +332,40 @@ def atexit_callback():
waiting_to_reset = False

# main loop
last_left_button_state = None
left_button_pressed = False
while True:
# timestamp of the current time
now = ticks_ms()

# attempt mouse read
try:
# try to read data from the mouse, small timeout so the code will move on
# quickly if there is no data
data_len = mouse.read(mouse_endpoint_address, buf, timeout=20)
buttons = mouse_ptr.update()

# Extract button states
if buttons is None or last_left_button_state is None:
current_left_button_state = 0
else:
current_left_button_state = 1 if 'left' in buttons else 0

# if there was data, then update the mouse cursor on the display
# using min and max to keep it within the bounds of the display
mouse_tg.x = max(0, min(display.width - 1, mouse_tg.x + buf[1] // 2))
mouse_tg.y = max(0, min(display.height - 1, mouse_tg.y + buf[2] // 2))
# Detect button presses
if current_left_button_state == 1 and last_left_button_state == 0:
left_button_pressed = True
elif current_left_button_state == 0 and last_left_button_state == 1:
left_button_pressed = False

# timeout error is raised if no data was read within the allotted timeout
except usb.core.USBTimeoutError:
# no problem, just go on
pass
# Update button states
last_left_button_state = current_left_button_state

# if the current state is title screen
if CUR_STATE == STATE_TITLE:
# if the left mouse button was clicked
if buf[0] & (1 << 0) != 0:
if left_button_pressed:
# change the current state to playing
CUR_STATE = STATE_PLAYING
# hide the title screen
title_screen_tg.hidden = True
# change the mouse cursor color to match the current player
mouse_bmp.pixel_shader[2] = colors[current_turn_index]
mouse_tg.pixel_shader[2] = colors[current_turn_index]

# if the current state is playing
elif CUR_STATE == STATE_PLAYING:
Expand Down Expand Up @@ -455,15 +439,20 @@ def atexit_callback():
current_player_lbl.color = colors[current_turn_index]

# update the color of the mouse cursor
mouse_bmp.pixel_shader[2] = colors[current_turn_index]
mouse_tg.pixel_shader[2] = colors[current_turn_index]

# empty out the cards flipped this turn list
cards_flipped_this_turn = []

# ignore any clicks while the code is waiting to take reset cards
if now >= WAIT_UNTIL:
# left btn pressed
if buf[0] & (1 << 0) != 0:
if left_button_pressed:
# if the mouse point is within the exit button
if (mouse_tg.x >= display.width - 30 and
mouse_tg.y >= display.height - 15):
# restart back to code.py
supervisor.reload()

# loop over all cards
for card_index, card in enumerate(card_tgs):
Expand Down Expand Up @@ -491,7 +480,7 @@ def atexit_callback():
# if the current state is gameover
elif CUR_STATE == STATE_GAMEOVER:
# left btn pressed
if buf[0] & (1 << 0) != 0:
if left_button_pressed:
# get the coordinates of the mouse cursor point
coords = (mouse_tg.x, mouse_tg.y, 0)

Expand All @@ -500,7 +489,7 @@ def atexit_callback():
if play_again_btn.contains(coords):
# set next code file to this one
supervisor.set_next_code_file(__file__,
working_directory=Path(__file__).parent.absolute())
working_directory=Path(__file__).parent.absolute())
# reload
supervisor.reload()

Expand Down