From fb1b34cecc86dc3c88d5d6a7de2c8b32a7546c47 Mon Sep 17 00:00:00 2001 From: frank Date: Mon, 20 Feb 2023 22:22:35 -0500 Subject: [PATCH] add GPIO input detection --- Playzing.py | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/Playzing.py b/Playzing.py index 8ac8c13..8f545a4 100755 --- a/Playzing.py +++ b/Playzing.py @@ -6,8 +6,18 @@ import argparse, os, pathlib, pygame, sys import lib.pgfw.pgfw as pgfw from games.ibitfit.electric_sieve.ElectricSieve import ElectricSieve +# Import GPIO library if available +try: + import RPi.GPIO as GPIO +except ImportError: + pass + class Playzing(pgfw.Game): + # The GPIO pins corresponding to the buttons + PIN_BUTTON_LEFT = 17 + PIN_BUTTON_RIGHT = 27 + def __init__(self, config_overrides=None): """ Create logo sprite, clear screen, and subscribe to events. @@ -35,6 +45,10 @@ class Playzing(pgfw.Game): # Clear screen to black self.get_display_surface().fill(self.configuration.get("display", "clear")) + # Initialize GPIO input and callbacks if GPIO library is loaded + if "RPi.GPIO" in sys.modules: + self.initialize_gpio() + # Subscribe to PGFW command events self.subscribe(self.respond) @@ -53,6 +67,45 @@ class Playzing(pgfw.Game): self.register(self.reveal_text, interval=40) self.play(self.animate_logo, play_once=True) + def initialize_gpio(self): + """ + Set pin numbering mode to GPIO, initialize all buttons to input pullup. + """ + # Use GPIO numbering + GPIO.setmode(GPIO.BCM) + + # Set button pins to pullup and attach to each a callback that runs on press or release + for pin in self.PIN_BUTTON_LEFT, self.PIN_BUTTON_RIGHT: + GPIO.setup(pin, GPIO.IN, pull_up_down=GPIO.PUD_UP) + GPIO.add_event_detect(pin, GPIO.BOTH, self.gpio_input) + + def gpio_input(self, pin): + """ + Translate GPIO input into PGFW commands, so Raspberry Pi wired controllers be used for input. + + Compare the pin state to what is stored in memory. Only fire an event if there has been a change in state. A change + from high to low triggers a press event. A change from low to high triggers a press cancel event. + + @param pin Raspberry Pi pin number as read by the RPi.GPIO library + """ + # Print the input state of each pin if debug is requested on the command line + if "--debug" in sys.argv: + pin_name = "left" if pin == self.PIN_BUTTON_LEFT else "right" + left_pin_state = GPIO.input(self.PIN_BUTTON_LEFT) + right_pin_state = GPIO.input(self.PIN_BUTTON_RIGHT) + print(f"Received {pin} ({pin_name}) input. Left state is {left_pin_state}. Right state is {right_pin_state}") + + # If the saved state of the pin is the same, there hasn't been a real button press or release, so don't continue + if self.pin_states[pin] != GPIO.input(pin): + self.pin_states[pin] = GPIO.input(pin) + # A high signal means the button is released, and a low signal means it is pressed + cancel = not (GPIO.input(pin) == GPIO.LOW) + if pin == self.PIN_BUTTON_LEFT: + self.input.post_command("left", cancel=cancel) + elif pin == self.PIN_BUTTON_RIGHT: + self.input.post_command("right", cancel=cancel) + self.input.post_any_command(id=pin, cancel=cancel) + @property def rotated(self): return self.configuration.get("display", "rotated")