forked from adafruit/Adafruit-Retrogame
-
Notifications
You must be signed in to change notification settings - Fork 0
/
arcadeBonnet.py
95 lines (82 loc) · 3.03 KB
/
arcadeBonnet.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#!/usr/bin/python
# Somewhat minimal Adafruit Arcade Bonnet handler. Runs in background,
# translates inputs from MCP23017 port expander to virtual USB keyboard
# events. Not -quite- as efficient or featuretastic as retrogame, but
# still reasonably lightweight and may be easier and/or more reliable than
# retrogame for some users. Supports ONE port expander, no regular GPIO
# (non-port-expander) or "Vulcan nerve pinch" features.
# Prerequisites:
# sudo apt-get install python-pip python-smbus python-dev
# sudo pip install evdev
# Be sure to enable I2C via raspi-config. Also, udev rules will need to
# be set up per retrogame directions.
# Credit to Pimoroni for Picade HAT scripts as starting point.
import os
import time
import RPi.GPIO as gpio
from evdev import uinput, UInput, ecodes as e
from smbus import SMBus
key = [ # EDIT KEYCODES IN THIS TABLE TO YOUR PREFERENCES:
# See /usr/include/linux/input.h for keycode names
# Keyboard Bonnet EmulationStation
e.KEY_LEFTCTRL, # 1A 'A' button
e.KEY_LEFTALT, # 1B 'B' button
e.KEY_A, # 1C 'X' button
e.KEY_S, # 1D 'Y' button
e.KEY_5, # 1E 'Select' button
e.KEY_1, # 1F 'Start' button
0, # Bit 6 NOT CONNECTED on Bonnet
0, # Bit 7 NOT CONNECTED on Bonnet
e.KEY_DOWN, # 4-way down D-pad down
e.KEY_UP, # 4-way up D-pad up
e.KEY_RIGHT, # 4-way right D-pad right
e.KEY_LEFT, # 4-way left D-pad left
e.KEY_L, # Analog right
e.KEY_H, # Analog left
e.KEY_J, # Analog down
e.KEY_K # Analog up
]
addr = 0x26 # I2C Address of MCP23017
irqPin = 17 # IRQ pin for MCP23017
os.system("sudo modprobe uinput")
ui = UInput({e.EV_KEY: key}, name="retrogame", bustype=e.BUS_USB)
bus = SMBus(1)
IODIRA = 0x00
IOCONA = 0x0A
INTCAPA = 0x10
# Initial MCP23017 config:
bus.write_byte_data(addr, 0x05 , 0x00) # If bank 1, switch to 0
bus.write_byte_data(addr, IOCONA, 0x44) # Bank 0, INTB=A, seq, OD IRQ
# Read/modify/write remaining MCP23017 config:
cfg = bus.read_i2c_block_data(addr, IODIRA, 14)
cfg[ 0] = 0xFF # Input bits
cfg[ 1] = 0xFF
cfg[ 2] = 0x00 # Polarity
cfg[ 3] = 0x00
cfg[ 4] = 0xFF # Interrupt pins
cfg[ 5] = 0xFF
cfg[12] = 0xFF # Pull-ups
cfg[13] = 0xFF
bus.write_i2c_block_data(addr, IODIRA, cfg)
# Clear interrupt by reading INTCAP and GPIO registers
x = bus.read_i2c_block_data(addr, INTCAPA, 4)
oldState = x[2] | (x[3] << 8)
# Callback for MCP23017 interrupt request
def mcp_irq(pin):
global oldState
x = bus.read_i2c_block_data(addr, INTCAPA, 4)
newState = x[2] | (x[3] << 8)
for i in range(16):
bit = 1 << i
lvl = newState & bit
if lvl != (oldState & bit):
ui.write(e.EV_KEY, key[i], 0 if lvl else 1)
ui.syn()
oldState = newState
# GPIO init
gpio.setwarnings(False)
gpio.setmode(gpio.BCM)
# Enable pullup and callback on MCP23017 IRQ pin
gpio.setup(irqPin, gpio.IN, pull_up_down=gpio.PUD_UP)
gpio.add_event_detect(irqPin, gpio.FALLING, callback=mcp_irq)
while True: time.sleep(1)