# [SCRAPEBOARD] is an arcade game in development by [@diskmem] & [@snakesandrews] # # It requires custom hardware to play but can be tested in keyboard mode without # the hardware. For more information on setting up and running the game, see # README.md. For information on the game in general, see . # # Full open source code is available at . # # This module can be imported and used to check on the status of connections between four GPIO # inputs on the Raspberry Pi for detecting the pads in Scrapeboard. # # It can also be run as a diagnostic script, in which case it prints connections detected between # the input GPIO pins. Use the `-h` flag to print the options. # # $ python3 gpio.py -h # # Original algorithm by Dr. Clement Shimizu is taken from his Arduino code in serial/serial.ino import time, itertools, argparse import RPi.GPIO as GPIO # These represent the game pads and the GPIO pins they're connected to LNW, LNE, LSE, LSW = range(4) pins = { LNW: 26, LNE: 19, LSE: 13, LSW: 6 } def initialize_gpio(): """ Set pin numbering mode to GPIO and initialize all pins to input pullup. """ # Use GPIO numbering GPIO.setmode(GPIO.BCM) # Set all pins to pullup for pin_id, pin in pins.items(): GPIO.setup(pin, GPIO.IN, pull_up_down=GPIO.PUD_UP) def connection2(pin_a, pin_b): """ Set `pin_a` to output a low signal, and set every other pin to pullup. If `pin_b` reads a low signal even though it's set to pullup, that means `pin_a` is connected to it, so return `True`. @param pin_a Pin which will be set to output LOW @param pin_b Pin which will be read @return `True` if a low signal is sent from `pin_a` to `pin_b`, `False` otherwise """ for pin_id, pin in pins.items(): if pin == pin_a: # Set pin_a to output LOW GPIO.setup(pin, GPIO.OUT) GPIO.output(pin, GPIO.LOW) else: # Set all other pins to input pullup GPIO.setup(pin, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Force 25ns delay between comparisons time.sleep(0.025) # pin_b can now be tested to see if if reads the LOW signal from pin_a return GPIO.input(pin_b) == GPIO.LOW def connection(pin_a, pin_b): """ Tests low signals connect from both A to B and from B to A @param pin_a Test if this pin is connected to `pin_b` @param pin_b Test if this pin is connected to `pin_a` @return `True` if `pin_a` and `pin_b` are connected, `False` otherwise """ return connection2(pin_a, pin_b) and connection2(pin_b, pin_a) def connections(): """ Look at all six possible connections between the four pins and return the state of each as a single dict. @return A dict with one entry per combination of pins, the key is a tuple of pin IDs, and the value is the state of connection """ state = {} for pin_id_a, pin_id_b in itertools.combinations(pins, 2): if connection(pins[pin_id_a], pins[pin_id_b]): state[(pin_id_a, pin_id_b)] = True else: state[(pin_id_a, pin_id_b)] = False return state def activity(): """ Look at all six possible connections between the four pins, and if a pin appears in any active connection, consider it active. Return the active state of all four pins as a dict. @return A dict with one entry per pin. The key is the pin ID, and the value is the state of whether it's active (a.k.a. pressed) """ # Create a dict of pins all at False state = pins.copy() for pin in state.keys(): state[pin] = False # Check all six combinations. If a pin appears in a connection, update its state to True. for pin_id_a, pin_id_b in itertools.combinations(pins, 2): if connection(pins[pin_id_a], pins[pin_id_b]): state[pin_id_a] = True state[pin_id_b] = True return state if __name__ == "__main__": # Set up and parse CLI parser = argparse.ArgumentParser() parser.add_argument("--connections", action="store_true") parser.add_argument("--activity", action="store_true") arguments = parser.parse_args() initialize_gpio() while True: if arguments.connections or not arguments.activity: # Try all connections once each frame for connection_ids, connection_state in connections().items(): # Only print connected combinations of pins if connection_state: pin_id_a, pin_id_b = connection_ids print(f"{pin_id_a} ({pins[pin_id_a]}) <-> {pin_id_b} ({pins[pin_id_b]})") else: pin_activity = activity() print(f"LNW {int(pin_activity[LNW])} LNE {int(pin_activity[LNE])} LSE {int(pin_activity[LSE])} LSW {int(pin_activity[LSW])}")