Created
September 16, 2016 22:11
-
-
Save jburgess777/8c39781f55fe64a6e938a37ec3a01f50 to your computer and use it in GitHub Desktop.
Tilda SNES controller
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import pyb | |
# SNES Connector pinout: | |
# | |
# ----------------- | |
# | 1 2 3 4 | 5 6 7 > | |
# ----------------- | |
# | |
# 1 +5V - Connect to vBAT | |
# 2 Clock } Connect to any unused data pin and specify | |
# 3 Latch } when creating the SNESpad object | |
# 4 Data } | |
# 5 unused | |
# 6 unused | |
# 7 Ground - Connect to 0v | |
SNES_B=1<<0 | |
SNES_Y=1<<1 | |
SNES_SELECT=1<<2 | |
SNES_START=1<<3 | |
SNES_UP=1<<4 | |
SNES_DOWN=1<<5 | |
SNES_LEFT=1<<6 | |
SNES_RIGHT=1<<7 | |
SNES_A=1<<8 | |
SNES_X=1<<9 | |
SNES_L=1<<10 | |
SNES_R=1<<11 | |
class SNESpad: | |
"""Read buttons from SNES game controllers | |
For a single controller the latch, clock and data pins must be specified. | |
When using multiple controllers there is one data pin per controller | |
specified in a list. The latch and clock pins are shared. | |
Usage: | |
c = SNESpad(latch="X8", clock="X7", data=["X1", "X2", "X3", "X9"]) | |
print("Press some buttons on the controller") | |
last=None | |
while True: | |
state = c.read() | |
for i in range(len(state)): | |
if last is None or state[i] != last[i]: | |
pressed = c.buttons(state[i]) | |
print("Controller %d buttons: %s" % (i+1, pressed)) | |
last=list(state) | |
""" | |
def __init__(self, latch, clock, data): | |
self.pin_latch = pyb.Pin(latch, pyb.Pin.OUT_PP) | |
self.pin_clock = pyb.Pin(clock, pyb.Pin.OUT_PP) | |
self.pin_data = [] | |
if type(data) is str: | |
data = [ data ] | |
for p in data: | |
self.pin_data.append(pyb.Pin(p, pyb.Pin.IN)) | |
self.data_count = len(self.pin_data) | |
def read(self): | |
# Latch current button state into buffer | |
self.pin_latch.high() | |
self.pin_latch.low() | |
# Clear initial state for all data pins | |
state = [] | |
for i in range(self.data_count): | |
state.append(0) | |
# Read 12 bits of button data | |
for i in range(12): | |
# Read button bit for each controller | |
# Buttons are active low | |
for j in range(self.data_count): | |
if not self.pin_data[j].value(): | |
state[j] |= 1 << i | |
# Clock in next button bit from buffer | |
self.pin_clock.high() | |
self.pin_clock.low() | |
return state | |
def buttons(self, state): | |
# Decode the bitmap into a list of buttons | |
pressed=[] | |
if (state & SNES_A): | |
pressed.append("A") | |
if (state & SNES_B): | |
pressed.append("B") | |
if (state & SNES_X): | |
pressed.append("X") | |
if (state & SNES_Y): | |
pressed.append("Y") | |
if (state & SNES_L): | |
pressed.append("L") | |
if (state & SNES_R): | |
pressed.append("R") | |
if (state & SNES_SELECT): | |
pressed.append("SELECT") | |
if (state & SNES_START): | |
pressed.append("START") | |
if (state & SNES_UP): | |
pressed.append("UP") | |
if (state & SNES_DOWN): | |
pressed.append("DOWN") | |
if (state & SNES_LEFT): | |
pressed.append("LEFT") | |
if (state & SNES_RIGHT): | |
pressed.append("RIGHT") | |
return pressed | |
if __name__ == '__main__': | |
c = SNESpad(latch="X8", clock="X7", data="X9") | |
print("Press some buttons on the controller") | |
last=None | |
while True: | |
state = c.read() | |
for i in range(len(state)): | |
if last is None or state[i] != last[i]: | |
pressed = c.buttons(state[i]) | |
print("Controller %d buttons: %s" % (i+1, pressed)) | |
last=list(state) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment