Skip to content

Add debouncer support for B,Select and Start buttons. #34

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
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
90 changes: 74 additions & 16 deletions adafruit_cursorcontrol/cursorcontrol_cursormanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,45 +236,103 @@ def _check_cursor_movement(self) -> None:


class DebouncedCursorManager(CursorManager):
"""Simple interaction user interface interaction for Adafruit_CursorControl.
This subclass provide a debounced version on the A button and provides queries for when
the button is just pressed, and just released, as well it's current state. "Just" in this
context means "since the previous call to update."
"""Simple user interface interaction for Adafruit_CursorControl.
This subclass provide a debounced version on the A, B, Start or Select buttons
and provides queries for when the buttons are just pressed, and just released,
as well their current state. "Just" in this context means "since the previous call to update."

:param Cursor cursor: The cursor object we are using.
"""

def __init__(self, cursor: Cursor, debounce_interval: float = 0.01) -> None:
CursorManager.__init__(self, cursor)
self._debouncer = Debouncer(
lambda: bool(self._pad_states & (1 << self._pad_btns["btn_a"])),
interval=debounce_interval,
)
self._debouncers = {}
for btn in self._pad_btns:
self._debouncers[btn] = Debouncer(
lambda btn=btn: bool((self._pad_states & (1 << self._pad_btns[btn]))),
interval=debounce_interval,
)

@property
def is_clicked(self) -> bool:
"""Returns True if the cursor button was pressed
"""Returns True if the cursor A button was pressed
during previous call to update()
"""
return self._debouncers["btn_a"].rose

@property
def is_alt_clicked(self) -> bool:
"""Returns True if the cursor B button was pressed
during previous call to update()
"""
return self._debouncer.rose
return self._debouncers["btn_b"].rose

pressed = is_clicked
@property
def is_select_clicked(self) -> bool:
"""Returns True if the Select button was pressed
during previous call to update()
"""
return self._debouncers["btn_select"].rose

@property
def is_start_clicked(self) -> bool:
"""Returns True if the Start button was pressed
during previous call to update()
"""
return self._debouncers["btn_start"].rose

@property
def released(self) -> bool:
"""Returns True if the cursor button was released
"""Returns True if the cursor A button was released
during previous call to update()
"""
return self._debouncers["btn_a"].fell

@property
def alt_released(self) -> bool:
"""Returns True if the cursor B button was released
during previous call to update()
"""
return self._debouncer.fell
return self._debouncers["btn_b"].fell

@property
def start_released(self) -> bool:
"""Returns True if the cursor Start button was released
during previous call to update()
"""
return self._debouncers["btn_start"].fell

@property
def select_released(self) -> bool:
"""Returns True if the cursor Select button was released
during previous call to update()
"""
return self._debouncers["btn_select"].fell

@property
def held(self) -> bool:
"""Returns True if the cursor button is currently being held"""
return self._debouncer.value
"""Returns True if the cursor A button is currently being held"""
return self._debouncers["btn_a"].value

@property
def alt_held(self) -> bool:
"""Returns True if the cursor B button is currently being held"""
return self._debouncers["btn_b"].value

@property
def start_held(self) -> bool:
"""Returns True if the cursor Start button is currently being held"""
return self._debouncers["btn_start"].value

@property
def select_held(self) -> bool:
"""Returns True if the cursor Select is currently being held"""
return self._debouncers["btn_select"].value

def update(self) -> None:
"""Updates the cursor object."""
if self._pad.events.get_into(self._event):
self._store_button_states()
self._check_cursor_movement()
self._debouncer.update()
for debouncer in self._debouncers.values():
debouncer.update()
158 changes: 158 additions & 0 deletions examples/cursorcontrol_buttons_debounced.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
# SPDX-FileCopyrightText: 2022 flom84 for Adafruit Industries
# SPDX-License-Identifier: MIT

import time
import board
import displayio
import terminalio

from adafruit_button import Button
from adafruit_cursorcontrol.cursorcontrol import Cursor
from adafruit_cursorcontrol.cursorcontrol_cursormanager import DebouncedCursorManager

SELECT_BUTTON_X = 0
SELECT_BUTTON_Y = 103
SELECT_BUTTON_WIDTH = 60
SELECT_BUTTON_HEIGHT = 25
SELECT_BUTTON_STYLE = Button.ROUNDRECT
SELECT_BUTTON_OUTLINE_COLOR = 0xFFFFFF
SELECT_BUTTON_LABEL = "Select"
SELECT_BUTTON_LABEL_COLOR = 0xFFFFFF

START_BUTTON_X = 100
START_BUTTON_Y = 103
START_BUTTON_WIDTH = 60
START_BUTTON_HEIGHT = 25
START_BUTTON_STYLE = Button.ROUNDRECT
START_BUTTON_OUTLINE_COLOR = 0xFFFFFF
START_BUTTON_LABEL = "Start"
START_BUTTON_LABEL_COLOR = 0xFFFFFF

A_BUTTON_X = 120
A_BUTTON_Y = 20
A_BUTTON_WIDTH = 30
A_BUTTON_HEIGHT = 30
A_BUTTON_STYLE = Button.ROUNDRECT
A_BUTTON_OUTLINE_COLOR = 0xFFFFFF
A_BUTTON_LABEL = "A"
A_BUTTON_LABEL_COLOR = 0xFFFFFF

B_BUTTON_X = 80
B_BUTTON_Y = 30
B_BUTTON_WIDTH = 30
B_BUTTON_HEIGHT = 30
B_BUTTON_STYLE = Button.ROUNDRECT
B_BUTTON_OUTLINE_COLOR = 0xFFFFFF
B_BUTTON_LABEL = "B"
B_BUTTON_LABEL_COLOR = 0xFFFFFF

BUTTON_FILL_PURPLE = 0xB400FF
BUTTON_FILL_BLACK = 0x000000

start_button = Button(
x=START_BUTTON_X,
y=START_BUTTON_Y,
width=START_BUTTON_WIDTH,
height=START_BUTTON_HEIGHT,
style=START_BUTTON_STYLE,
fill_color=BUTTON_FILL_BLACK,
outline_color=START_BUTTON_OUTLINE_COLOR,
label=START_BUTTON_LABEL,
label_font=terminalio.FONT,
label_color=START_BUTTON_LABEL_COLOR,
)

select_button = Button(
x=SELECT_BUTTON_X,
y=SELECT_BUTTON_Y,
width=SELECT_BUTTON_WIDTH,
height=SELECT_BUTTON_HEIGHT,
style=SELECT_BUTTON_STYLE,
fill_color=BUTTON_FILL_BLACK,
outline_color=SELECT_BUTTON_OUTLINE_COLOR,
label=SELECT_BUTTON_LABEL,
label_font=terminalio.FONT,
label_color=SELECT_BUTTON_LABEL_COLOR,
)

a_button = Button(
x=A_BUTTON_X,
y=A_BUTTON_Y,
width=A_BUTTON_WIDTH,
height=A_BUTTON_HEIGHT,
style=A_BUTTON_STYLE,
fill_color=BUTTON_FILL_BLACK,
outline_color=A_BUTTON_OUTLINE_COLOR,
label=A_BUTTON_LABEL,
label_font=terminalio.FONT,
label_color=A_BUTTON_LABEL_COLOR,
)

b_button = Button(
x=B_BUTTON_X,
y=B_BUTTON_Y,
width=B_BUTTON_WIDTH,
height=B_BUTTON_HEIGHT,
style=B_BUTTON_STYLE,
fill_color=BUTTON_FILL_BLACK,
outline_color=B_BUTTON_OUTLINE_COLOR,
label=B_BUTTON_LABEL,
label_font=terminalio.FONT,
label_color=B_BUTTON_LABEL_COLOR,
)

# Create the display
display = board.DISPLAY

# Create the display context
splash = displayio.Group()

# initialize the mouse cursor object
mouse_cursor = Cursor(display, display_group=splash)

# initialize the debounced cursor manager
debounced_cursor = DebouncedCursorManager(mouse_cursor)

# create displayio group
splash.append(start_button)
splash.append(select_button)
splash.append(a_button)
splash.append(b_button)
display.show(splash)

while True:
debounced_cursor.update()

if debounced_cursor.is_clicked:
a_button.fill_color = BUTTON_FILL_PURPLE
print("A pressed: " + str(debounced_cursor.held))

if debounced_cursor.released:
a_button.fill_color = BUTTON_FILL_BLACK
print("A pressed: " + str(debounced_cursor.held))

if debounced_cursor.is_alt_clicked:
b_button.fill_color = BUTTON_FILL_PURPLE
print("B pressed: " + str(debounced_cursor.alt_held))

if debounced_cursor.alt_released:
b_button.fill_color = BUTTON_FILL_BLACK
print("B pressed: " + str(debounced_cursor.alt_held))

if debounced_cursor.is_start_clicked:
start_button.fill_color = BUTTON_FILL_PURPLE
print("Start pressed: " + str(debounced_cursor.start_held))

if debounced_cursor.start_released:
start_button.fill_color = BUTTON_FILL_BLACK
print("Start pressed: " + str(debounced_cursor.start_held))

if debounced_cursor.is_select_clicked:
select_button.fill_color = BUTTON_FILL_PURPLE
print("Select pressed: " + str(debounced_cursor.select_held))

if debounced_cursor.select_released:
select_button.fill_color = BUTTON_FILL_BLACK
print("Select pressed: " + str(debounced_cursor.select_held))

time.sleep(0.01)